android v7兼容包RecyclerView的使用(四)——点击事件的不同方式处理

前三篇文章

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();

            }
        });

后面两个参数可以传空值,代表不设置监听器。

运行效果图如下。

我们会发现,上面的代码耦合性还是有点高,事件直接与适配器发生了耦合,除此之外,我们还应该有更好的方法来处理这个点击事件。是的,不是有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

时间: 2024-12-14 03:02:51

android v7兼容包RecyclerView的使用(四)——点击事件的不同方式处理的相关文章

android v7兼容包RecyclerView的使用(三)——布局管理器的使用

前两篇文章 android v7兼容包RecyclerView的使用(二) android v7兼容包RecyclerView的使用(一) 介绍了RecyclerView的基本用法以及与它相关的重要的几个类,本篇文章介绍布局管理器的具体用法. 为了演示布局管理器的使用,找了很多个例子,都没有找到感觉合适的例子,后来google了一把,发现了一个比较适合说明问题的例子.所以就拿该例子来解释吧. 在演示布局管理器前,我们先把UI部分搭建完成.由于使用到了V7兼容包的另一个包CardView,所以在这

android v7兼容包RecyclerView的使用(二)

上篇文章 android v7兼容包RecyclerView的使用(一)讲了RecyclerView的最基本用法,现在开始挖掘更详细的内容. 在RecyclerView的API中,有这样一句话 A flexible view for providing a limited window into a large data set. 大致意思就是:当有大量的数据显示在一个有限大小的窗口上时,RecyclerView就是解决这种情况的一个灵活的View. 从以上描述可以看出RecyclerView的

android v7兼容包RecyclerView的使用(一)

什么是RecyclerView?个人理解,它是一个在数据量大的时候,为了显示在界面上提供的灵活高效处理的控件.可以替代listview,gallery,gridview等控件. 如何使用?本篇文章只是热热身,不会过多介绍细节. 首先需要导入\sdk\extras\android\support\v7\recyclerview\libs\android-support-v7-recyclerview.jar包,如果sdk目录下没有该文件,则adt版本可能太低,建议升级或者从网上下载该库. Recy

V7兼容包——调色板Palette的使用

之前写过四篇文章是关于v7兼容包RecyclerView的使用 android v7兼容包RecyclerView的使用(四)--点击事件的不同方式处理 android v7兼容包RecyclerView的使用(三)--布局管理器的使用 android v7兼容包RecyclerView的使用(二) android v7兼容包RecyclerView的使用(一) 今天无意看到一个v7兼容包中另一个库Palette,就学习了下,这个库有什么作用呢,说白了就是用它实现动态颜色的设置. Materia

转:android Support 兼容包详解

本文转自stormzhang的ANDROID SUPPORT兼容包详解 背景 来自于知乎上邀请回答的一个问题Android中AppCompat和Holo的一个问题?, 看来很多人还是对这些兼容包搞不清楚,那么干脆写篇博客吧. Support Library 我们都知道Android一些SDK比较分裂,为此google官方提供了Android Support Library package 系列的包来保证高版本sdk开发的向下兼容性, 所以你可能经常看到v4,v7,v13这些数字,首先我们就来理清

从头开始学 RecyclerView(二) 添加item点击事件

不管了,先来张图 偶吐了个槽 item点击事件必须手动添加,默认并没有一个显式的API接口可供调用. 为了节约学习时间,网上找了篇很不错的文章.这里基本就复制了. 添加点击事件 RecyclerView#addOnItemTouchListener 分析 查看RecyclerView源码可以看到,RecyclerView预留了一个Item的触摸事件方法: public void addOnItemTouchListener(OnItemTouchListener listener) { mOnI

Android中点击事件的实现方式

在之前博文中多次使用了点击事件的处理实现,有朋友就问了,发现了很多按钮的点击实现,但有很多博文中使用的实现方式有都不一样,到底是怎么回事.今天我们就汇总一下点击事件的实现方式. 点击事件的实现大致分为以下三种: (1)Activity 实现接口方式实现点击事件(经常使用) (2)自定义方法,使用配置文件android:onclick (3)使用内部类方式实现 (4)使用匿名内部类实现介绍下几种点击事件的实现方式: 下面我们通过代码来简单演示下几种点击事件的实现方式: (1)Activity 实现

Android Support兼容包详解

转载:http://stormzhang.com/android/2015/03/29/android-support-library/ 背景 来自于知乎上邀请回答的一个问题Android中AppCompat和Holo的一个问题?, 看来很多人还是对这些兼容包搞不清楚,那么干脆写篇博客吧. Support Library 我们都知道Android一些SDK比较分裂,为此google官方提供了Android Support Library package 系列的包来保证高版本sdk开发的向下兼容性

33、Android Support兼容包详解(转载)

原文转自:微信分享 2015-03-31 22:11 背景 来自于知乎上邀请回答的一个问题Android中AppCompat和Holo的一个问题?, 看来很多人还是对这些兼容包搞不清楚,那么干脆写篇博客吧. 一.Support Library 我们都知道Android一些SDK比较分裂,为此google官方提供了Android Support Library package 系列的包来保证高版本sdk开发的向下兼容性, 所以你可能经常看到v4,v7,v13这些数字,首先我们就来理清楚这些数字的含