一.序言
网上有很多实现该需求的,只是太多花哨的功能没用到,与自己项目需求契合性不高,用起来能用,但是改源码太麻烦,就自己写了个。
1.1效果图
二.步骤
要么重写recyclerview,要么重写item。我这里选择重写item。
2.1 实现item布局
如下图所示,你要把item的布局弄成下面这样。
布局文件是:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<!--分割线 -->
<View
android:layout_width="match_parent"
android:layout_height="10dp"
/>
<com.maxence.tvfocusdemo.ItemView
android:id="@+id/itemview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scrollbars="none"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal"
>
<TextView
android:id="@+id/tv1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="我是item"
android:textColor="@android:color/white"
android:background="#0000ff"
android:gravity="center"
/>
<TextView
android:id="@+id/tv2"
android:layout_width="60dp"
android:layout_height="60dp"
android:text="删除"
android:textColor="@android:color/white"
android:background="#ff0000"
android:gravity="center"
/>
</LinearLayout>
</com.maxence.tvfocusdemo.ItemView>
</LinearLayout>
我这里是重写HorizontalScrollView。
public class ItemView extends HorizontalScrollView {
2.1.1 获取屏幕的宽度,然后准备动态设置item左边的view填充满屏幕,然后右边的删除view被挤出屏幕外:
public ItemView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
init();
}
private void init() {
WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
int pixels = metrics.widthPixels;
mScreenWidth = pixels;
}
2.1.2在onmeasure动态设置item左边填充满屏幕:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (!islayout) { //这里做一个判断是由于onMeasure onlayout会执行多次
vg = (LinearLayout) getChildAt(0);
//左边的view
view = (TextView) vg.getChildAt(0);
//右边的view,暂时不在这里取
// View view1 = vg.getChildAt(1);
//设置左边的view宽度填充蛮屏幕
android.widget.LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(mScreenWidth, LinearLayout.LayoutParams.MATCH_PARENT);
view.setLayoutParams(params);
islayout = true;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
2.1.3 获取右边删除item的宽度,便于在后面滑动中,判断滑动距离,自动打开或者自动关闭该item
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (!islayout) { //这里做一个判断是由于onMeasure onlayout会执行多次
vg = (LinearLayout) getChildAt(0); //HorizontalScrollView只能有一个子控件。在布局文件中,我是用LinearLayout
//左边的view
view = (TextView) vg.getChildAt(0);
//右边的view,暂时不在这里取
// View view1 = vg.getChildAt(1);
//设置左边的view宽度填充蛮屏幕
android.widget.LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(mScreenWidth, LinearLayout.LayoutParams.MATCH_PARENT);
view.setLayoutParams(params);
islayout = true;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
2.2实现在左滑右滑过程中,能自动隐藏打开
监听onTouchEvent,我们只需监听up和cancel状态即可:
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
//用于记录当前的
case MotionEvent.ACTION_DOWN:
if(mylistener!=null){
mylistener.onlick(this);
}
return true;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
int scrollX = getScrollX();
if(scrollX>=viewWidth/2){
openMenu();
}else{
closeMenu();
}
//直接break的话 smoothScrollTo方法不生效
return true;
default:
break;
}
return super.onTouchEvent(ev);
}
这里说下scrollto和scrollBy的区别:
scrollTo:滑动到指定的坐标,多次设置无效
scrollBy: 滑动坐标值的加减,每次滑动以上一次滑动坐标为原点
/**
* 显示完整右侧view
*/
public void openMenu(){
smoothScrollTo(viewWidth,0);
mylistener.open(this);
//adapter.setOpenView(this);
}
/**
* 关闭右侧view
*/
public void closeMenu(){
smoothScrollTo(0, 0);
}
2.3点击其他item的时候,关闭掉正在打开的item
我们这里有回调函数实现:
interface Mylistener{
void onlick(ItemView v);
void open(ItemView v);
}
然后在 action_down判断是否需要关闭:
//用于记录当前的
case MotionEvent.ACTION_DOWN:
if(mylistener!=null){
mylistener.onlick(this);
}
return true;
对外,也就是adpater页面提供个监听方法:
public void setOnMyListener(Mylistener l){
mylistener=l;
}
apadter具体实现:
holder.itView.setOnMyListener(new Mylistener() {
@Override
public void onlick(ItemView v) {
if(mItemView!=null&&mItemView!=v){
mItemView.closeMenu();
}
}
@Override
public void open(ItemView v) {
mItemView=v;
}
});
2.4实现点击删除item:
在adapter中监听
holder.tv_r.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
holder.itView.closeMenu();
aList.remove(position);
notifyDataSetChanged();
}
});
以下是设置item置顶的,不需要可以不用
holder.tv_r.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
holder.itView.closeMenu();
String string = aList.get(position);
aList.remove(position);
aList.add(0,string);
notifyDataSetChanged();
}
});
这样基本搞定:
附上adapter完整代码:
public class MyAdapter extends RecyclerView.Adapter<Holder> {
private Context mContext;
private ArrayList<String> aList;
private ItemView mItemView;
private MyAdapter adapter;
public MyAdapter(Context context) {
mContext=context;
aList=new ArrayList<String>();
for(int x=0;x<20;x++){
aList.add(x+"");
}
}
@Override
public int getItemCount() {
return aList.size();
}
@Override
public void onBindViewHolder(final Holder holder, final int position) {
holder.tv_l.setText("这是条目:"+aList.get(position));
holder.tv_r.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
holder.itView.closeMenu();
String string = aList.get(position);
aList.remove(position);
aList.add(0,string);
notifyDataSetChanged();
}
});
holder.itView.setOnMyListener(new Mylistener() {
@Override
public void onlick(ItemView v) {
if(mItemView!=null&&mItemView!=v){
mItemView.closeMenu();
}
}
@Override
public void open(ItemView v) {
mItemView=v;
}
});
}
@Override
public Holder onCreateViewHolder(ViewGroup parent, int arg1) {
LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.activity_main1,parent,false);
return new Holder(view);
}
class Holder extends RecyclerView.ViewHolder{
TextView tv_l;
TextView tv_r;
ItemView itView;
public Holder(View itemView) {
super(itemView);
tv_l = (TextView) itemView.findViewById(R.id.tv1);
tv_r = (TextView) itemView.findViewById(R.id.tv2);
itView=(ItemView) itemView.findViewById(R.id.itemview);
}
}
}
actity中简单调用即可:
recyclerView = (RecyclerView) findViewById(R.id.rl_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
MyAdapter adapter =new MyAdapter(this);
recyclerView.setAdapter(adapter);
代码传送门eclipse版