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

Android RecyclerView单击、长按事件标准实现:基于OnItemTouchListener + GestureDetector的更多相关文章

  1. Android RecyclerView单击、长按事件:基于OnItemTouchListener +GestureDetector标准实现(二),封装抽取成通用工具类

     Android RecyclerView单击.长按事件:基于OnItemTouchListener +GestureDetector标准实现(二),封装抽取成通用工具类 我写的附录文章2,介绍了 ...

  2. Android学习笔记长按事件的处理

    常见的长按事件 代码示例: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedIns ...

  3. android的单击监听事件

    Button button = (Button) findViewById(R.id.button1); //1.直接new出来 button.setOnClickListener(new View. ...

  4. RecyclerView的单击和长按事件(转)

    转自:http://www.jianshu.com/p/f2e0463e5aef 前言 上一篇文章揭开RecyclerView的神秘面纱(一):RecyclerView的基本使用中,主要讲述了Recy ...

  5. Android系统中自定义按键的短按、双击、长按事件

    在项目中碰到这样的问题: 由于系统中的按键在底层做了重新定义或者新增了按键,此时需要在APP层对按键事件(keyevent)做分解处理,模拟Android系统做法,把keyevent分解成: 1.单击 ...

  6. android listview综合使用示例_结合数据库操作和listitem单击长按等事件处理

    本示例说明: 1.自定义listview条目样式,自定义listview显示列数的多少,灵活与数据库中字段绑定. 2.实现对DB的增删改查,并且操作后listview自动刷新. 3.响应用户操作点击事 ...

  7. Android 自定义View实现单击和双击事件

    自定义View, 1. 自定义一个Runnable线程TouchEventCountThread ,  用来统计500ms内的点击次数 2. 在MyView中的 onTouchEvent 中调用 上面 ...

  8. android listview综合使用演示样例_结合数据库操作和listitem单击长按等事件处理

    本演示样例说明: 1.自己定义listview条目样式,自己定义listview显示列数的多少,灵活与数据库中字段绑定. 2.实现对DB的增删改查,而且操作后listview自己主动刷新. 3.响应用 ...

  9. Android开发 ---基本UI组件5:监听下拉选项,动态绑定下拉选项、全选/反选,取多选按钮的值,长按事件,长按删除,适配器的使用,提示查询数据,activity控制多按钮

    效果图: 效果描述: 1.当点击 1 按钮后,进入选择城市的页面,会监听到你选中的城市名称:动态为Spinner绑定数据 2.当点击 2 按钮后,进入自动查询数据页面,只要输入首字母,就会动态查找以该 ...

随机推荐

  1. 用Dictionary替换switch case

    用switch case处理一个很长的判断,例如56个民族01代表汉族,02代表藏族,03代表壮族...,当传入数字想获取民族名称时就得写56个case,当传入民族获取背后的数字时,又得再写56个ca ...

  2. 高宽不定的div相对父div上下、左右居中

    <div class="parent"> <div class="child">123</div> </div> ...

  3. 从零开始HTML(二 2016/9/20)

    1.布局 ① 使用 <div> 元素的 HTML 布局,<div> 元素常用作布局工具,因为能够轻松地通过 CSS 对其进行定位. <!DOCTYPE html> ...

  4. 讲解Python中的递归函数

    本文的最重要的收获在于:尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式. 在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数. 举个例 ...

  5. Android pulltorefresh使用

    pulltorefresh插件可以轻松实现上拉下拉刷新,github.com上直接搜索进行下载. 布局文件: <RelativeLayout xmlns:android="http:/ ...

  6. USACO2016Splitting the Field分割牧场

    Description FJ的N头奶牛分别位于他二维的牧场的不同位置.FJ想用一个矩形栅栏围住这些牛(牛可以在栅栏边上),并使这个栅栏尽可能小.这个栅栏的边与x轴或y轴平行.不幸的是,FJ上个季度的牛 ...

  7. spring profile 多环境配置管理

    本地.测试.开发.产品等不同环境文件配置 现象   如果在开发时进行一些数据库测试,希望链接到一个测试的数据库,以避免对开发数据库的影响.   开发时的某些配置比如log4j日志的级别,和生产环境又有 ...

  8. postgresql - 事务

    1.事务的使用 begin;//开启关闭自动提交的事务 insert into testtab01 values(0); rollback;//事务回滚 2.SavePoint的使用 begin;// ...

  9. WCF双向通信,心跳

    合肥程序员群:49313181.    合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入)Q  Q:408365330     E-Mail:egojit@qq.com WCF中双程 ...

  10. NGINX 内存池有感

    写在前面 写NGINX系列的随笔,一来总结学到的东西,二来记录下疑惑的地方,在接下来的学习过程中去解决疑惑. 也希望同样对NGINX感兴趣的朋友能够解答我的疑惑,或者共同探讨研究. 整个NGINX系列 ...