RecyclerView进阶(二)点击事件的实现

来源:互联网 发布:两个矩阵的协方差公式 编辑:程序博客网 时间:2024/05/16 07:47

个人总结、笔记之用,如有错误欢迎指正。

先列出来LayoutManager的常用方法:

  • findFirstVisibleItemPosition()返回当前第一个可见 Item 的 position
  • findFirstCompletelyVisibleItemPosition() 返回当前第一个完全可见 Item 的 position
  • findLastVisibleItemPosition() 返回当前最后一个可见 Item 的 position
  • findLastCompletelyVisibleItemPosition() 返回当前最后一个完全可见 Item 的 position.
  • scrollBy()滚动到某个位置。

一、模仿ListView实现

RecyclerView并没有提供ListView中常用的OnItemClickListener。所以需要我们来自定义一个相应的接口,Adapter就是一个很好的地方。
1.定义接口

/**     * 自定义点击接口     */    public static interface onRecyclerItemClickListener{        /**         * item view回调方法         * @param view 被点击的view         * @param position 点击索引         */        void onItemClick(View view,int position);        void onLongItemClick(View view, int position);    }

2.添加接口和初始化方法

//初始化private onRecyclerItemClickListener mOnRecyclerItemClickListener = null;//初始化方法    public void setOnRecyclerItemClickListener(onRecyclerItemClickListener onRecyclerItemClickListener) {        mOnRecyclerItemClickListener = onRecyclerItemClickListener;    }

3.在初始化时候添加点击事件

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener{    @Override    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, final int i) {        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);        ViewHolder vh = new ViewHolder(view);        //将创建的View注册点击事件        view.setOnClickListener(this);        return vh;    }    @Override    public void onBindViewHolder(ViewHolder viewHolder, final int i) {        viewHolder.mTextView.setText(datas.get(i).title);        //将数据保存在itemView的Tag中,以便点击时进行获取        viewHolder.itemView.setTag(position);    }    ...    //将点击事件转移给外面的调用者    @Override    public void onClick(View v) {        if (mOnItemClickListener != null) {            //注意这里使用getTag方法获取数据            mOnItemClickListener.onItemClick(v,v.getTag());        }    }    ...}

4.在Activity中调用

mAdapter.setOnRecyclerItemClickListener(new MyAdapter.onRecyclerItemClickListener() {            @Override            public void onItemClick(View view, int position) {                Toast.makeText(RecyclerViewActivity.this, "点击事件", Toast.LENGTH_LONG).show();            }        });

这种方式实现起来比较简单,但是显而易见,对性能是不友好的。

二、OnItemTouchListener实现

官方提供了一个OnItemTouchListener接口,用来处理相应的触摸事件。并且提供了一个实现类SimpleOnItemTouchListener,这是一个有空方法体和默认返回值的实现类。

You may prefer to extend this class if you don’t need to override all methods. Another benefit of using this class is future compatibility. As the interface may change, we’ll always provide a default implementation on this class so that your code won’t break when you update to a new version of the support library.

继承这个类可以很方便的实现简单的点击事件。先来看看这个类

 public static class SimpleOnItemTouchListener implements RecyclerView.OnItemTouchListener {        @Override        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {            return false;        }        @Override        public void onTouchEvent(RecyclerView rv, MotionEvent e) {        }        @Override        public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {        }    }

只有简单的三个方法。第一个是处理触摸事件的,第二个是拦截触摸事件的,第三个是处理触摸冲突的。
实际上,实现OnItemTouchListener必须实现的也就是这三个方法。

OnTouchEvent()中,当触摸时会回调一个MotionEvent对象,我们通过使用GestureDetectorCompat来解析用户的操作.

这里我们选择通过实现OnItemTouchListener来实现点击监听。

public abstract class OnRecyclerItemClickListener implements RecyclerView.OnItemTouchListener {    private RecyclerView mRecyclerView;    private GestureDetectorCompat mGestureDetector;    public OnRecyclerItemClickListener(RecyclerView recyclerView) {        this.mRecyclerView = recyclerView;        this.mGestureDetector = new GestureDetectorCompat(mRecyclerView.getContext(),new MyGestureListener());    }    public abstract  void onItemClick(View view, int position);    public abstract void onLongItemClick(View view, int position);    @Override    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {        mGestureDetector.onTouchEvent(e);        return false;    }    @Override    public void onTouchEvent(RecyclerView rv, MotionEvent e) {        mGestureDetector.onTouchEvent(e);    }    @Override    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {    }    private class MyGestureListener extends GestureDetector.SimpleOnGestureListener{        /**         * 单击抬起回调         */        @Override        public boolean onSingleTapUp(MotionEvent e) {            View child = mRecyclerView.findChildViewUnder(e.getX(), e.getY());            if (child != null) {                //RecyclerView.ViewHolder viewHolder = mRecyclerView.getChildViewHolder(child);                onItemClick(child,mRecyclerView.getChildAdapterPosition(child));            }            return true;        }        /**         * @param e         */        @Override        public void onLongPress(MotionEvent e) {            View child = mRecyclerView.findChildViewUnder(e.getX(), e.getY());            if (child != null) {               // RecyclerView.ViewHolder viewHolder = mRecyclerView.getChildViewHolder(child);                onLongItemClick(child,mRecyclerView.getChildAdapterPosition(child));            }        }    }}

在GestureDetectorCompat的手势回调中我们覆写:

  • boolean onSingleTapUp(MotionEvent e)单击抬起回调
  • void onLongPress(MotionEvent e)长按回调

在RecyclerView的对象中添加addOnItemTouchListener()方法,然后在回调中处理你需要的事件

 mRecyclerView.addOnItemTouchListener(new OnRecyclerItemClickListener(mRecyclerView) {            @Override            public void onItemClick(View view, int position) {                Toast.makeText(RecyclerViewActivity.this,"点击事件",Toast.LENGTH_SHORT).show();            }            @Override            public void onLongItemClick(View view, int position) {                Toast.makeText(RecyclerViewActivity.this,"长按事件",Toast.LENGTH_SHORT).show();            }        });    }

参考:http://blog.devwiki.net/index.php/2016/07/24/three-ways-click-recyclerview-item.html
参考:https://segmentfault.com/a/1190000005176416

0 0
原创粉丝点击