Compose LazyColumn中可点击AndroidView消费滚动事件的解决方案问询
问题根因
该问题是Compose 1.0.x版本中AndroidView与原生View的触摸事件分发逻辑不兼容导致的:
原生可点击View(如Button)会消费ACTION_DOWN触摸事件(onTouchEvent返回true),而Compose滚动容器的滚动判定需要接收完整的DOWN->MOVE事件流,由于DOWN事件被原生View直接消费,Compose的LazyColumn无法接收后续的MOVE事件,也就无法触发滚动逻辑。
纯Composable组件、RecyclerView嵌套Composable的场景都有配套的事件分发兼容逻辑,所以不会出现该问题。
可行解决方案
方案1:升级Compose版本(优先推荐)
该问题在Compose 1.1.0及以上版本已经被官方修复,你只需要将项目Compose版本升级到1.1.0+,同步配套升级Kotlin版本到1.6.0+即可,无需修改业务代码。
方案2:修改原生可点击View的触摸事件逻辑(适配低版本Compose)
如果受项目约束暂时无法升级Compose版本,可以给原生可点击View添加触摸监听,在检测到垂直滚动动作时通知父容器接管事件,不会影响原有点击逻辑,实现代码如下:
LazyColumn { items(100) { idx -> AndroidView( factory = { ctx -> val touchSlop = ViewConfiguration.get(ctx).scaledTouchSlop var downX = 0f var downY = 0f LinearLayout(ctx).apply { orientation = LinearLayout.VERTICAL addView(TextView(ctx).apply { text = "Non-clickable view $idx" }) addView(android.widget.Button(ctx).apply { text = "Clickable view $idx" setOnClickListener { // 原有点击逻辑不受影响 } setOnTouchListener { v, event -> when (event.action) { MotionEvent.ACTION_DOWN -> { downX = event.x downY = event.y } MotionEvent.ACTION_MOVE -> { val dx = kotlin.math.abs(event.x - downX) val dy = kotlin.math.abs(event.y - downY) // 判定为垂直滚动时,通知父容器可以拦截事件处理滚动 if (dy > touchSlop && dy > dx) { v.parent.requestDisallowInterceptTouchEvent(false) } } } // 返回false,不拦截原有触摸逻辑,点击事件可以正常触发 false } }) } } ) } }
内容的提问来源于stack exchange,提问作者fikr4n
相关产品推荐
相关产品推荐

