前三篇文章
android v7兼容包RecyclerView的使用(三)——布局管理器的使用
android v7兼容包RecyclerView的使用(二)
android v7兼容包RecyclerView的使用(一)
介绍了RecyclerView的使用以及常见的相关类和布局管理器的灵活之处。写了这么多篇,还没涉及到用户交互,那么怎么处理点击事件呢。

在RecyclerView中你会惊奇的发现,该类中并没有OnItemClickListener监听器监听我们的单击事件,也没有OnItemLongClickListener监听器监听我们的长按事件。取而代之的是OnItemTouchListener监听器,那么该怎样实现我们的点击事件和长按事件呢。

我们的代码是基于上篇文章布局管理器的代码,在其基础上加入事件监听。

假设让我们自己来事件点击事件,我们比方会使用ViewHolder来间接处理事件。首先在适配器中添加监听器接口。

    interface OnItemClickListener {        void onClick(View v);    }    interface OnItemLongClickListener {        void onLongClick(View v);    }    private OnItemClickListener onClickListener;    private OnItemLongClickListener onLongClickListener;

然后重载构造函数,使其能够接收监听器实例

    public CardViewAdapter(String[] data) {        this(data, null, null);    }    public CardViewAdapter(String[] data, OnItemClickListener onClickListener) {        this(data, onClickListener, null);    }    public CardViewAdapter(String[] data, OnItemClickListener onClickListener,            OnItemLongClickListener onLongClickListener) {        this.data = data;        this.onClickListener = onClickListener;        this.onLongClickListener = onLongClickListener;    }

终于会调用三參数的构造器,在该构造器内完毕赋值。

将原来的ViewHolder构造函数进行改造,使其处理点击事件,当然也能够直接在onCreateViewHolder函数里处理点击事件。

    public ViewHolder(View itemLayoutView,                final OnItemClickListener onClickListener,                final OnItemLongClickListener onLongClickListener) {            super(itemLayoutView);            info = (TextView) itemLayoutView.findViewById(R.id.info_text);            itemLayoutView.setOnClickListener(new OnClickListener() {                @Override                public void onClick(View v) {                //在监听器不为空的时候,进行回调                    if (onClickListener != null) {                        onClickListener.onClick(v);                    }                }            });            itemLayoutView.setOnLongClickListener(new OnLongClickListener() {                @Override                public boolean onLongClick(View v) {                //在监听器不为空的时候,进行回调                    if (onLongClickListener != null) {                        onLongClickListener.onLongClick(v);                    }                    //返回true,消费掉该事件,阻止其继续传递                    return true;                }            });        }

细致一看,事实上代码还是挺多的,那么让我们调用一下。

    mAdapter = new CardViewAdapter(data,new OnItemClickListener() {            @Override            public void onClick(View v) {                TextView info = (TextView) v.findViewById(R.id.info_text);                Toast.makeText(getApplicationContext(), "单击"+info.getText(), Toast.LENGTH_LONG).show();            }        },new OnItemLongClickListener() {            @Override            public void onLongClick(View v) {                TextView info = (TextView) v.findViewById(R.id.info_text);                Toast.makeText(getApplicationContext(), "长按"+info.getText(), Toast.LENGTH_LONG).show();            }        });

后面两个參数能够传空值,代表不设置监听器。
执行效果图例如以下。
RecyclerView点击事件
我们会发现,上面的代码耦合性还是有点高,事件直接与适配器发生了耦合,除此之外,我们还应该有更好的方法来处理这个点击事件。是的,不是有OnItemTouchListener监听器吗,再配合手势不就能够吗。
好了,看代码吧,详解在凝视中。

package cn.edu.zafu.layoutmanager;import android.content.Context;import android.support.v7.widget.RecyclerView;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.View;/** * 监听器,实现OnItemTouchListener接口 * * @author lizhangqu * * 2015-3-12 */public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {    private OnItemClickListener mListener;    private GestureDetector mGestureDetector;    // 点击回调    public interface OnItemClickListener {        public void onItemClick(View view, int position);        public void onItemLongClick(View view, int position);    }    public RecyclerItemClickListener(Context context,            final RecyclerView recyclerView, OnItemClickListener listener) {        mListener = listener;        // 识别并处理手势        mGestureDetector = new GestureDetector(context,                new GestureDetector.SimpleOnGestureListener() {                    @Override                    public boolean onSingleTapUp(MotionEvent e) {                        // 轻击触摸屏后,弹起,必须返回true,否则无法触发单击                        return true;                    }                    @Override                    public void onLongPress(MotionEvent e) {                        // 长按                        // 依据findChildViewUnder(float x, float y)来算出哪个item被选择了                        View childView = recyclerView.findChildViewUnder(                                e.getX(), e.getY());                        // 有item被选则且监听器不为空触发长按事件                        if (childView != null && mListener != null) {                            mListener.onItemLongClick(childView,                                    recyclerView.getChildPosition(childView));                        }                    }                });    }    @Override    public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {        View childView = view.findChildViewUnder(e.getX(), e.getY());        if (childView != null && mListener != null                && mGestureDetector.onTouchEvent(e)) {            // 触发单击事件            mListener.onItemClick(childView, view.getChildPosition(childView));            return true;        }        return false;    }    @Override    public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {    }}

在activity中调用

    mRecyclerView.addOnItemTouchListener(new RecyclerItemClickListener(getApplicationContext(), mRecyclerView, new OnItemClickListener() {            @Override            public void onItemLongClick(View view, int position) {                Toast.makeText(getApplicationContext(), "长按"+data[position], Toast.LENGTH_SHORT).show();            }            @Override            public void onItemClick(View view, int position) {                Toast.makeText(getApplicationContext(), "短按"+data[position], Toast.LENGTH_SHORT).show();            }        }));

非常明显,另外一种方式与适配器进行了解耦。应该说优于第一种方法。
那么还有没有方法处理点击事件呢。让我们从万能的github上搜索一下。
https://github.com/lucasr/twoway-view
在该项目的sample文件夹下有个类里面有这样一段代码

 final ItemClickSupport itemClick = ItemClickSupport.addTo(mRecyclerView);        itemClick.setOnItemClickListener(new OnItemClickListener() {            @Override            public void onItemClick(RecyclerView parent, View child, int position, long id) {                mToast.setText("Item clicked: " + position);                mToast.show();            }        });        itemClick.setOnItemLongClickListener(new OnItemLongClickListener() {            @Override            public boolean onItemLongClick(RecyclerView parent, View child, int position, long id) {                mToast.setText("Item long pressed: " + position);                mToast.show();                return true;            }        });

上述代码有个ItemClickSupport 类,对的,该类就是提供事件的支持。那么该类在哪里呢,事实上它在该项目的core文件夹下。我直接将其该文件夹下的代码拷至我的项目的包中,删除一个不相关的类,就直接使用了,当然还须要拷一个资源文件就是ids.xml

实际执行效果呢,是跟上面两种方式是一样的,那么它的实现由什么差别呢,事实上与另外一种方式没什么大的差别,基本上就是OnItemTouchListener 加手势实现的,仅仅只是其逻辑可能更加严谨,设计更加优秀罢了。除此之外,该文件夹下另一个ItemSelectionSupport类,该类提供了item选择的功能,提供了单选多选方式,然而呢,在我測试时发现存在bug,所以呢,这个类的使用就跳过了。

至此,RecyclerView的点击事件就处理完了。

源代码下载
http://download.csdn.net/detail/sbsujjbcy/8495337

更多相关文章

  1. 简单明了的分析Android触摸事件,看完再也不纠结了
  2. Android Studio按钮响应事件(三)
  3. 【Android - 进阶】之事件分发机制
  4. Android事件分发机制完全解析(终极版二)
  5. Android事件分发机制和一些疑问
  6. android 开发中判断网络是否连接的代码
  7. android设置横屏代码
  8. Android查询:模拟键盘鼠标事件(adb shell 实现)
  9. Android数据库代码备忘

随机推荐

  1. Android官方教程翻译(6)——添加ActionBar
  2. Android 中的 BACK 和 HOME 按钮的区别
  3. Android开机广播和关机广播
  4. Android 调用手机震动
  5. Android RSA 加密(分段加密)
  6. 简单说说android的线程封装
  7. ViewPager使用样例
  8. Android基础知识学习——界面转换
  9. android studio设置自动导入
  10. 【android】Sax解析半个例子 :startElemen