Jetpack Compose通过MutableState传递MotionEvent时y坐标异常偏移问题
问题排查与修复方案
根因
- Android 系统对
MotionEvent采用对象池复用机制,你在pointerInteropFilter回调中拿到的事件是临时对象,回调结束后系统会回收该对象并修改其字段值。你直接将事件引用存入MutableState,后续Canvas读取时引用指向的对象已经被系统修改,所以出现y坐标异常的问题,和MutableState本身无关。
修复方案
有两种可选实现,推荐第二种更稳定:
方案1:存储复制后的独立MotionEvent对象
拿到事件后先复制一份再存入State,避免被系统复用修改,使用完成后主动回收避免内存泄漏:
// 处理器赋值逻辑修改为 mutableMotionEvent.value?.recycle() // 先回收上一次的事件 mutableMotionEvent.value = MotionEvent.obtain(event) // 复制独立事件存储
方案2(推荐):提取需要的字段存自定义数据类
不需要完整保留MotionEvent的所有属性,仅提取需要的坐标、动作类型等字段封装成自定义类,不需要处理回收逻辑,性能更好:
// 1. 定义自定义触摸事件数据类 data class TouchPoint( val x: Float, val y: Float, val action: Int ) // 2. 修改MutableState定义 val touchState: MutableState<TouchPoint?> = remember { mutableStateOf(value = null, policy = neverEqualPolicy()) } // 3. 处理器赋值逻辑 touchState.value = TouchPoint( x = event.x, y = event.y, action = event.action ) // 4. Canvas端读取逻辑 Canvas( modifier = Modifier .fillMaxSize() .border(border = BorderStroke(1.dp, Color.Green)) ) { touchState.value?.let { drawCircle(Color.Red, center = Offset(it.x, it.y), radius = 4f) } }
额外说明
你之前加neverEqualPolicy的配置是正确的,默认的相等性判断策略会过滤掉数值相同的连续事件,导致后续事件无法触发Canvas重组。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

