简单实现RecyclerView侧滑删除菜单,简单明了,移植性强

  一.序言

   网上有很多实现该需求的,只是太多花哨的功能没用到,与自己项目需求契合性不高,用起来能用,但是改源码太麻烦,就自己写了个。

  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版

  as版


  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值