You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 16:45:02