使用SelectionTracker时为RecyclerView项内子控件添加点击事件
RecyclerView + SelectionTracker 子控件点击额外弹窗实现方案
问题根因
两个异常的本质原因很明确:
findChildViewUnder()本身设计就是只返回RecyclerView的直接子View(也就是列表项的根布局),不会递归遍历深层子控件,自然拿不到id为vp的TextView- SelectionTracker的触摸监听器优先级高于RecyclerView子View的点击事件分发,事件在传到子控件之前就被SelectionTracker拦截,所以直接给子控件设置
OnClickListener不会生效
可直接落地的实现步骤
全程不需要改动原有选中逻辑,侵入性极低:
- 第一步:修改自定义
ItemDetailsLookup.ItemDetails的实现,增加点击热点判定
重写热点判定方法,识别点击位置是否落在vp控件范围内,原有选中逻辑的判定保持不变,保证整个item区域点击都能正常触发选中:// 你的自定义ItemDetails类内部 override fun inSelectionHotspot(e: MotionEvent): Boolean { // 保持原有逻辑,整个item区域都触发选中,不破坏原有能力 return true } override fun inItemClickHotspot(e: MotionEvent): Boolean { val currentItemView = itemView // 将RecyclerView层级的触摸坐标转换为当前item内部的相对坐标 val xInItem = e.x - currentItemView.left val yInItem = e.y - currentItemView.top val vpView = currentItemView.findViewById<TextView>(R.id.vp) // 判断触摸点是否落在vp控件的绘制区域内 return xInItem >= vpView.left && xInItem <= vpView.right && yInItem >= vpView.top && yInItem <= vpView.bottom } - 第二步:给SelectionTracker绑定激活点击监听,处理弹窗逻辑
这个监听只会在你上面判定的vp区域被点击时触发,返回false就不会阻断SelectionTracker的原有选中流程:selectionTracker.onItemActivatedListener = OnItemActivatedListener { item, _ -> val clickPosition = item.position val extraTip = dataList[clickPosition].fullContent // 这里写你的弹窗逻辑,展示extraTip showSupplementTipDialog(extraTip) // 返回false表示不消费事件,后续选中逻辑正常执行 false } - 第三步:检查列表项布局中
vp控件的属性,不要设置android:clickable="true"或者android:focusable="true",避免子控件自行抢占触摸事件,所有事件判定统一交给SelectionTracker处理即可。
踩坑提示:不要尝试通过降低SelectionTracker的触摸监听优先级、或者给item根布局重写onTouchEvent的方式实现,会导致列表滚动、长按选中、多选等原生能力出现异常。
内容的提问来源于stack exchange,提问作者Tupsi
相关产品推荐
相关产品推荐

