RecyclerView中CustomView触摸处理与ItemTouchHelper的冲突问题
解决方案
1. 修正CustomView的事件拦截逻辑
在onInterceptTouchEvent中,必须在ACTION_DOWN事件触发时立即阻止父布局(RecyclerView)拦截事件——因为ACTION_DOWN是触摸事件序列的起点,父布局会在这个阶段判断是否接管后续事件,晚一步都会导致事件被抢。
public class CustomView extends View { @Override public boolean onInterceptTouchEvent(MotionEvent ev) { // 捕获ACTION_DOWN时立即禁用父布局的事件拦截 if (ev.getAction() == MotionEvent.ACTION_DOWN) { getParent().requestDisallowInterceptTouchEvent(true); } // 拦截所有事件,交由自身onTouchEvent处理 return true; } @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_MOVE: // 在这里实现你的水平拖拽逻辑 break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: // 触摸结束后恢复父布局的事件拦截权限,避免影响其他条目 getParent().requestDisallowInterceptTouchEvent(false); break; } // 消费所有触摸事件 return true; } }
2. 让ItemTouchHelper避开CustomView的长按拖拽
自定义ItemTouchHelper.SimpleCallback,重写isLongPressDragEnabled方法,判断当前触摸的条目是否使用了CustomView,如果是则禁用长按拖拽,彻底避免ItemTouchHelper和CustomView抢事件。
public class MyItemTouchCallback extends ItemTouchHelper.SimpleCallback { private final RecyclerView mRecyclerView; public MyItemTouchCallback(int dragDirs, int swipeDirs, RecyclerView recyclerView) { super(dragDirs, swipeDirs); mRecyclerView = recyclerView; } @Override public boolean isLongPressDragEnabled() { // 获取当前触摸的子View View touchedView = mRecyclerView.findChildViewUnder(mRecyclerView.getTouchX(), mRecyclerView.getTouchY()); if (touchedView != null) { RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(touchedView); // 判断条目根布局是否为CustomView if (holder.itemView instanceof CustomView) { return false; // 禁用长按拖拽 } } return true; // 其他条目保留长按拖拽功能 } // 以下是原有逻辑,保持不变 @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { // 实现条目拖拽交换逻辑 return true; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { // 实现水平滑动逻辑 } }
3. 绑定ItemTouchHelper时传入RecyclerView
初始化ItemTouchHelper时把RecyclerView传进去,确保isLongPressDragEnabled能准确获取到当前触摸的条目:
ItemTouchHelper touchHelper = new ItemTouchHelper(new MyItemTouchCallback( ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT, recyclerView )); touchHelper.attachToRecyclerView(recyclerView);
内容的提问来源于stack exchange,提问作者Basti
相关产品推荐
相关产品推荐

