Android RecyclerView单击、长按事件标准实现:基于OnItemTouchListener + GestureDetector

简介: Android RecyclerView单击、长按事件:基于OnItemTouchListener + GestureDetector标准实现Android RecyclerView虽然拥有ListView绝大多数...


Android RecyclerView单击、长按事件:基于OnItemTouchListener + GestureDetector标准实现

Android RecyclerView虽然拥有ListView绝大多数的功能,但Android RecyclerView却没有实现像ListView那样的点击事件、长按事件的标准实现方式,我在附录文章1中介绍的方式,实现了典型的RecyclerView的item点击事件,大致的思路是通过为RecyclerView的ViewHolder添加View.OnClickListener事件达到点击事件的监听,这种实现方式可以正常工作,但不太标准。现在给出一种较为规范的Android官方实现。
翻了Android RecyclerView的官方文档,这文档中确实没有提供像ListView的OnItem点击事件,但是注意到有一个addOnItemTouchListener,根据官方文档的描述,addOnItemTouchListener是Android官方文档中留下的点击事件的线索入口,文档中也暗示开发者应该从这个事件监听接口中实现所需的逻辑代码。但是直接new一个对象传递过去,则需要自己解析Android Touch Event复杂的处理,所幸Android官方给出了RecyclerView.SimpleOnItemTouchListener,顾名思义,就是一个简化的OnItemTouchListener。虽然有了SimpleOnItemTouchListener,到此还没完,因为SimpleOnItemTouchListener只是事件拦截处理的入口,真正要做事情的主角是:GestureDetector。通过GestureDetector里面的拦截到的所托管的单击、长按事件,才最终实现了RecyclerView的单击、长按事件。

完整代码:

package zhangphil.app;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private RecyclerView mRecyclerView;
    private GestureDetector mGestureDetector;

    //长按事件
    private OnItemLongClickListener mOnItemLongClickListener = new OnItemLongClickListener() {
        @Override
        public void onItemLongClick(int position, View childView) {
            Toast.makeText(getApplication(), "长按:" + position, Toast.LENGTH_SHORT).show();
        }
    };

    //单击事件
    private OnItemClickListener mOnItemClickListener = new OnItemClickListener() {
        @Override
        public void onItemClick(int position, View childView) {
            Toast.makeText(getApplication(), "单击:" + position, Toast.LENGTH_SHORT).show();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //创建一个简单的用以测试的RecyclerView
        mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(layoutManager);
        mRecyclerView.setAdapter(new ItemAdapter());


        //以下是添加点击、长按事件的关键代码

        mRecyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() {
            @Override
            public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
                if (mGestureDetector.onTouchEvent(e)) {
                    return true;
                }
                return false;
            }
        });

        mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {

            //长按事件
            @Override
            public void onLongPress(MotionEvent e) {
                super.onLongPress(e);
                if (mOnItemLongClickListener != null) {
                    View childView = mRecyclerView.findChildViewUnder(e.getX(), e.getY());
                    if (childView != null) {
                        int position = mRecyclerView.getChildLayoutPosition(childView);
                        mOnItemLongClickListener.onItemLongClick(position, childView);
                    }
                }
            }

            //单击事件
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                if (mOnItemClickListener != null) {
                    View childView = mRecyclerView.findChildViewUnder(e.getX(), e.getY());
                    if (childView != null) {
                        int position = mRecyclerView.getChildLayoutPosition(childView);
                        mOnItemClickListener.onItemClick(position, childView);
                        return true;
                    }
                }

                return super.onSingleTapUp(e);
            }
        });
    }

    //长按事件接口
    public interface OnItemLongClickListener {
        public void onItemLongClick(int position, View childView);
    }

    //单击事件接口
    public interface OnItemClickListener {
        public void onItemClick(int position, View childView);
    }


    private class ItemViewHolder extends RecyclerView.ViewHolder {
        public TextView text;

        public ItemViewHolder(View itemView) {
            super(itemView);
            text = (TextView) itemView.findViewById(android.R.id.text1);
        }
    }

    private class ItemAdapter extends RecyclerView.Adapter<ItemViewHolder> {

        @Override
        public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = View.inflate(parent.getContext(), android.R.layout.simple_list_item_1, null);
            ItemViewHolder holder = new ItemViewHolder(view);
            return holder;
        }

        @Override
        public void onBindViewHolder(ItemViewHolder holder, int position) {
            holder.text.setText(String.valueOf(position));
        }

        @Override
        public int getItemCount() {
            return 99;
        }
    }
}


因为我是在onInterceptTouchEvent里面拦截了RecyclerView的触摸事件,并通过GestureDetector
托管处理,由此可以延伸、进一步封装出更多更复杂的事件处理接口。


附录:
1,《RecyclerView点击事件》链接:http://blog.csdn.net/zhangphil/article/details/46771865



相关文章
|
3月前
|
API Android开发 开发者
Android UI设计: 什么是RecyclerView?为什么它比ListView更好?
Android UI设计: 什么是RecyclerView?为什么它比ListView更好?
31 2
|
4月前
|
XML Java Android开发
Android Studio App开发之捕获屏幕的变更事件实战(包括竖屏与横屏切换,回到桌面与切换到任务列表)
Android Studio App开发之捕获屏幕的变更事件实战(包括竖屏与横屏切换,回到桌面与切换到任务列表)
39 0
|
4月前
|
Java Android开发
Android Studio入门之按钮触控的解析及实战(附源码 超详细必看)(包括按钮控件、点击和长按事件、禁用与恢复按钮)
Android Studio入门之按钮触控的解析及实战(附源码 超详细必看)(包括按钮控件、点击和长按事件、禁用与恢复按钮)
171 0
|
4月前
|
小程序 JavaScript 前端开发
微信小程序(十七)小程序监听返回键跳转事件(安卓返回也适用)
onUnload:function(){ wx.redirectTo({ url: '../index/index' }) wx.navigateTo({ url: '../index/index' }) wx.switchTab({ url: '../../member/member' }) }
301 0
|
4月前
|
Android开发 Kotlin
android开发,使用kotlin学习滚动控件RecyclerView
android开发,使用kotlin学习滚动控件RecyclerView
36 0
|
4月前
|
XML Java Android开发
Android App事件交互Event之模仿京东App实现下拉刷新功能(附源码 可直接使用)
Android App事件交互Event之模仿京东App实现下拉刷新功能(附源码 可直接使用)
33 0
Android App事件交互Event之模仿京东App实现下拉刷新功能(附源码 可直接使用)
|
4月前
|
XML Java Android开发
Android App事件交互中辨别缩放与旋转手指的讲解与实战(附源码 可直接使用)
Android App事件交互中辨别缩放与旋转手指的讲解与实战(附源码 可直接使用)
36 0
|
4月前
|
XML Java Android开发
Android App事件交互中区分点击和长按动作以及识别手势滑动方向的讲解及实战(附源码 可直接使用)
Android App事件交互中区分点击和长按动作以及识别手势滑动方向的讲解及实战(附源码 可直接使用)
60 0
|
4月前
|
XML Java Android开发
Android App开发触摸事件中手势事件Event的分发流程讲解与实战(附源码 简单易懂)
Android App开发触摸事件中手势事件Event的分发流程讲解与实战(附源码 简单易懂)
43 0
|
4月前
|
XML 监控 Java
Android App开发之事件交互Event中检测软键盘和物理按键讲解及实战(附源码 演示简单易懂)
Android App开发之事件交互Event中检测软键盘和物理按键讲解及实战(附源码 演示简单易懂)
126 0