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

Android onTouchListener多触点时ACTION_MOVE仅首触点触发如何解决

问题成因
  • MotionEvent.ACTION_MOVE事件不绑定单个触点索引:getActionIndex()方法仅对ACTION_POINTER_DOWN、ACTION_POINTER_UP这类单触点触发的事件有效,在ACTION_MOVE场景下返回的值无实际意义,默认返回0,因此原代码仅会更新索引为0的触点位置,其余触点完全未被处理。
  • 单次ACTION_MOVE事件会携带当前所有活跃触点的位置信息,需要手动遍历所有触点索引才能完成全量位置更新,原代码只处理了单个索引的触点,因此后续触点不会触发位置更新逻辑。
修复方案

直接修改ACTION_MOVE分支的逻辑,遍历所有活跃触点逐个更新位置即可,修改后的触摸事件监听代码如下:

@SuppressLint("ClickableViewAccessibility")
public GluSurfaceView(Context context, AppCompatActivity main) {
    super(context);

    setEGLContextClientVersion(3);
    renderer = new com.glu.engine.Renderer(main);
    setRenderer(renderer);

    setOnTouchListener((view, motionEvent) -> {
        int actionIndex = MotionEventCompat.getActionIndex(motionEvent);
        int actionMasked = motionEvent.getActionMasked();

        if(actionMasked == MotionEvent.ACTION_MOVE){
            // 遍历所有活跃触点,逐个更新位置
            for (int i = 0; i < motionEvent.getPointerCount(); i++) {
                renderer.recordAction(i, motionEvent.getX(i),motionEvent.getY(i));
                Log.w("OnTouchListener","we recorded a change! "+i+" has moved.");
            }
            return true;
        }

        if(actionMasked == MotionEvent.ACTION_UP){
            renderer.stopAction(0);
            Log.w("onTouchListener","first Action stopped");
            return true;
        }

        if(actionMasked == MotionEvent.ACTION_DOWN){
            renderer.startAction(0);
            renderer.recordAction(0,motionEvent.getX(0),motionEvent.getY(0));
            Log.w("onTouchListener","first Action!");
            return true;
        }
        if(actionMasked == MotionEvent.ACTION_POINTER_DOWN){
            renderer.addPointer(actionIndex);
            renderer.recordAction(actionIndex,motionEvent.getX(actionIndex),motionEvent.getY(actionIndex));
            Log.w("onTouchListener","new Action! "+actionIndex);
            return true;
        }
        if(actionMasked == MotionEvent.ACTION_POINTER_UP) {
            renderer.removePointer(actionIndex);
            Log.w("onTouchListener","action "+actionIndex+" has stopped.");
            return true;
        }
        return false;
    });
}

额外优化建议

当前代码直接使用触点索引(index)作为标识存在潜在问题:当有中间触点抬起时,后续触点的索引会自动前移,可能导致存储的触点位置错乱。建议改用motionEvent.getPointerId(index)获取触点的唯一ID作为标识,索引仅用于读取当前事件的位置信息,用唯一ID匹配对应触点存储的数据,避免索引变动带来的异常。

内容的提问来源于stack exchange,提问作者user14587078

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 14:36:07