RecyclerView项同时处理OnTouchListener与OnClickListener问题求助
解决RecyclerView条目同时触发OnTouchListener与OnClickListener的问题
这个问题我之前也碰到过!核心原因就是你在OnTouchListener里返回了true,把整个触摸事件链都截断了——Android的点击事件需要完整的ACTION_DOWN→ACTION_UP流程才能触发,而你返回true相当于告诉系统“这个事件我全处理了,不用往下传了”,所以OnClickListener永远拿不到事件。
给你两种可行的解决方案,第一种最简洁:
方案一:修改OnTouchListener的返回值
只在ACTION_DOWN时处理拖拽逻辑,其他事件返回false,让事件继续传递给点击事件:
override fun onBindViewHolder(holder: ItemListViewHolder, position: Int) { val item = getItem(position) holder.bind(item) holder.itemView.cardview.setOnTouchListener { v, event -> if (event.action == MotionEvent.ACTION_DOWN) { Log.d(TAG, "onBindViewHolder: ${event.buttonState}") this.startDragListener.onStartDrag(holder) } // 返回false,允许事件继续传递,点击事件就能正常触发了 return@setOnTouchListener false } }
不用担心拖拽功能受影响:startDragListener.onStartDrag(holder)调用后,系统会接管后续的拖拽事件,和你返回false没有冲突。
方案二:手动在TouchListener中处理点击(适合复杂场景)
如果因为某些原因不能返回false,可以手动记录触摸坐标,在ACTION_UP时判断是否属于点击(坐标偏移很小),然后主动触发点击事件:
override fun onBindViewHolder(holder: ItemListViewHolder, position: Int) { val item = getItem(position) holder.bind(item) var downX = 0f var downY = 0f holder.itemView.cardview.setOnTouchListener { v, event -> when(event.action) { MotionEvent.ACTION_DOWN -> { downX = event.x downY = event.y Log.d(TAG, "onBindViewHolder: ${event.buttonState}") this.startDragListener.onStartDrag(holder) } MotionEvent.ACTION_UP -> { val offsetX = abs(event.x - downX) val offsetY = abs(event.y - downY) // 判断是否是点击(偏移量小于10px,可根据需求调整) if (offsetX < 10 && offsetY < 10) { holder.onClick(v) // 主动触发ViewHolder的点击逻辑 } } } return@setOnTouchListener true } }
两种方案里,方案一优先推荐,逻辑更简单也更符合Android事件传递的设计。
内容的提问来源于stack exchange,提问作者ScrapeW
相关产品推荐
相关产品推荐

