Android滑动事件与RecyclerView的item点击事件的冲突

博客指出对item根布局LinearLayout添加点击事件监听时,横向滑动item会触发点击事件。作者不明原因,给出了解决办法的参考链接https://www.jianshu.com/p/0180075c1bd4 。

对item的根布局LinearLayout添加点击事件的监听,但是在滑动item的时候(不是竖着滑,而是普通的随意地横向的滑),就会触发点击事件,不明所以。

解决办法:

mRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
            public float y1,y2,x2,x1;

            @Override
            public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
                if (e.getAction() == MotionEvent.ACTION_DOWN) {
                    x1 = e.getX();
                    y1 = e.getY();
                }
                if (e.getAction() == MotionEvent.ACTION_MOVE) {
                    x1 = e.getX();
                    y1 = e.getY();
                }
                if (e.getAction() == MotionEvent.ACTION_UP) {
                    x2 = e.getX();
                    y2 = e.getY();
                    if (Math.abs(x1 - x2) < 6) {
                        return false;// 距离较小,当作click事件来处理
                    }
                    if(Math.abs(x1 - x2) >60){  // 真正的onTouch事件
                        return true;
                    }
                }
                return false;

            }

            @Override
            public void onTouchEvent(RecyclerView rv, MotionEvent e) {

            }

            @Override
            public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

            }
        });

参考:https://www.jianshu.com/p/0180075c1bd4

 

 

 

<think> 我们使用Kotlin和Java两种方式来实现RecyclerViewitem点击事件。这里分别给出两种语言的实现示例。 ### Kotlin实现方式(推荐): 在Adapter中定义点击事件的回调接口,并在ViewHolder中设置点击监听。 ```kotlin class MyAdapter( private val dataList: List<DataItem>, private val onItemClick: (DataItem) -> Unit // 点击回调 ) : RecyclerView.Adapter<MyAdapter.ViewHolder>() { inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { // 初始化视图 init { view.setOnClickListener { val position = adapterPosition if (position != RecyclerView.NO_POSITION) { onItemClick(dataList[position]) } } } } // ... 其他Adapter方法(onCreateViewHolder, onBindViewHolder等)保持不变 ... } ``` 在Activity/Fragment中使用: ```kotlin recyclerView.adapter = MyAdapter(dataList) { item -> // 处理点击事件 Toast.makeText(this, "Clicked: ${item.title}", Toast.LENGTH_SHORT).show() } ``` ### Java实现方式: 在Adapter中定义接口: ```java public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { public interface OnItemClickListener { void onItemClick(DataItem item); } private List<DataItem> dataList; private OnItemClickListener listener; public MyAdapter(List<DataItem> dataList, OnItemClickListener listener) { this.dataList = dataList; this.listener = listener; } public class ViewHolder extends RecyclerView.ViewHolder { public ViewHolder(@NonNull View itemView) { super(itemView); itemView.setOnClickListener(v -> { int position = getAdapterPosition(); if (position != RecyclerView.NO_POSITION) { listener.onItemClick(dataList.get(position)); } }); } } // ... 其他方法 ... } ``` 在Activity/Fragment中使用: ```java recyclerView.setAdapter(new MyAdapter(dataList, new MyAdapter.OnItemClickListener() { @Override public void onItemClick(DataItem item) { Toast.makeText(MainActivity.this, "Clicked: " + item.getTitle(), Toast.LENGTH_SHORT).show(); } })); ``` ### 注意事项: 1. **防止无效位置**:使用`adapterPosition`(Kotlin)或`getAdapterPosition()`(Java)时,需要检查是否为`RecyclerView.NO_POSITION`,避免无效点击。 2. **防止重复点击**:如果需要防止快速重复点击,可以在点击事件中加入时间间隔判断。 3. **长按事件**:类似地,可以使用`setOnLongClickListener`实现长按事件。 ### 高级用法: - **使用ItemTouchHelper实现滑动删除**:通过`ItemTouchHelper`结合RecyclerView实现滑动删除,并在删除后通知Adapter更新。 - **使用共享元素转场**:在点击事件中触发Activity跳转时,可以添加共享元素动画效果。 §§相关问题§§ 1. 如何在RecyclerView中同时实现点击和长按事件? 2. 如何避免在快速滚动时因视图复用导致的点击事件错乱? 3. 当使用DataBinding时,如何在RecyclerView Adapter中处理点击事件? 4. 如何实现RecyclerView列表项的滑动删除和拖拽排序功能? </think> 在 AndroidX RecyclerView 中实现 item 点击事件主要有以下几种方式,下面我将介绍最常用的两种方法: ### 方法一:在 Adapter 内部实现(推荐) 这是最常用且封装性较好的实现方式: ```java public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { private List<ListItem> itemList; private OnItemClickListener listener; // 定义点击事件接口 public interface OnItemClickListener { void onItemClick(ListItem item, int position); } public MyAdapter(List<ListItem> itemList, OnItemClickListener listener) { this.itemList = itemList; this.listener = listener; } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.list_item, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { ListItem item = itemList.get(position); holder.titleView.setText(item.getTitle()); holder.subTitleView.setText(item.getSubTitle()); // 设置点击事件 holder.itemView.setOnClickListener(v -> { if (listener != null) { listener.onItemClick(item, position); } }); } public static class ViewHolder extends RecyclerView.ViewHolder { TextView titleView; TextView subTitleView; public ViewHolder(@NonNull View itemView) { super(itemView); titleView = itemView.findViewById(R.id.title_text); subTitleView = itemView.findViewById(R.id.subtitle_text); } } } ``` ### 方法二:在 ViewHolder 中实现 这种方式将点击事件处理放在 ViewHolder 内部: ```java public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { // ... 其他部分相同 ... public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { TextView titleView; TextView subTitleView; public ViewHolder(@NonNull View itemView) { super(itemView); titleView = itemView.findViewById(R.id.title_text); subTitleView = itemView.findViewById(R.id.subtitle_text); // 设置点击监听器 itemView.setOnClickListener(this); } @Override public void onClick(View v) { int position = getAdapterPosition(); if (position != RecyclerView.NO_POSITION && listener != null) { listener.onItemClick(itemList.get(position), position); } } } } ``` ### 在 Activity/Fragment 中使用 ```java // 在Activity/Fragment中初始化 RecyclerView recyclerView = findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new LinearLayoutManager(this)); List<ListItem> dataList = new ArrayList<>(); dataList.add(new ListItem("标题1", "副标题1")); dataList.add(new ListItem("标题2", "副标题2")); // 创建适配器并设置点击监听 MyAdapter adapter = new MyAdapter(dataList, (item, position) -> { // 处理点击事件 Toast.makeText(this, "点击了: " + item.getTitle(), Toast.LENGTH_SHORT).show(); // 也可以跳转到详情页等 // Intent intent = new Intent(this, DetailActivity.class); // intent.putExtra("item_data", item); // startActivity(intent); }); recyclerView.setAdapter(adapter); ``` ### 高级用法:添加长按事件 ```java // 在Adapter中添加长按事件接口 public interface OnItemLongClickListener { boolean onItemLongClick(ListItem item, int position); } // 在ViewHolder中设置长按监听 holder.itemView.setOnLongClickListener(v -> { if (listener != null) { listener.onItemLongClick(itemList.get(position), position); return true; } return false; }); // 在Activity中使用 adapter.setOnItemLongClickListener((item, position) -> { // 长按处理逻辑,如显示上下文菜单 showContextMenu(item); return true; }); ``` ### 注意事项: 1. **位置检查**:始终检查 `getAdapterPosition() != RecyclerView.NO_POSITION`,避免无效点击 2. **避免内存泄漏**:在 Fragment 中,在 `onDestroyView` 中清除监听器 3. **性能考虑**:不要在 `onClick` 中执行耗时操作 4. **事件冲突**:如果 item 内有可点击控件(如按钮),需要处理事件冲突
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值