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


    

    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



  • 相关阅读:
    MySQL 常用到的几个字符处理函数
    MySQL DATE_SUB查询工龄大于35的员工信息
    Mysql 没有nvl()函数,却有一个类似功能的函数ifnull();
    switch 循环中的case理解
    批处理系统和分时系统各具有什么特点?为什么分时系统的响应比较快?
    存储式计算机的主要特点是什么?
    代码实现导航栏分割线
    Keras函数式API介绍
    Keras通过子类(subclass)自定义神经网络模型
    R语言kohonen包主要函数介绍
  • 原文地址:https://www.cnblogs.com/hehehaha/p/6147237.html
Copyright © 2020-2023  润新知