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

如何设置InputDriver.emit()事件的触摸指针位置?

解决Android Things树莓派3触摸光标停在中心的问题

嘿,我帮你排查下这个光标一直停在屏幕中心的问题!看起来你的触摸事件发送逻辑缺了几个关键参数,而且可能还存在坐标方向不匹配的情况,咱们一步步来解决:

问题分析

你当前的代码只设置了触摸位置和接触状态,但Android的输入系统需要更完整的事件信息才能正确识别并移动光标,比如动作类型(按下/移动/抬起)、指针ID以及压力值。另外,触摸板的Y轴坐标方向通常和Android屏幕的Y轴方向相反(触摸板原点可能在左下角,而Android屏幕原点在左上角),这也会导致坐标映射错误。

解决方案

1. 修正InputDriver初始化,添加压力轴配置

首先,在InputDriver构建时添加压力轴的配置,因为Android输入系统期望触摸事件包含压力参数:

mInputDriver = new InputDriver.Builder()
    .setName("TouchPad")
    .setVendorId(0x1234) // 设置非0的Vendor/Product ID,部分系统要求
    .setProductId(0x5678)
    .setAxisConfiguration(MotionEvent.AXIS_X, 0, 800, 0, 0)
    .setAxisConfiguration(MotionEvent.AXIS_Y, 0, 480, 0, 0)
    .setAxisConfiguration(MotionEvent.AXIS_PRESSURE, 0, 1, 0, 0) // 新增压力轴配置
    .build();
UserDriverManager.getInstance().registerInputDriver(mInputDriver);

2. 完善触摸事件发送逻辑,补充必要参数

根据触摸的不同状态(按下、移动、抬起)发送对应的事件类型,并修正Y轴坐标:

// 处理触摸按下事件
private void sendTouchDown(int rawX, int rawY) {
    // 反转Y轴,适配Android屏幕坐标(原点在左上角)
    int adjustedY = 480 - rawY;
    
    mInputDriverEvent.clear();
    mInputDriverEvent.setAction(MotionEvent.ACTION_DOWN); // 设置动作类型为按下
    mInputDriverEvent.setPointerId(0); // 设置指针ID(单触摸场景用0即可)
    mInputDriverEvent.setPosition(MotionEvent.AXIS_X, rawX);
    mInputDriverEvent.setPosition(MotionEvent.AXIS_Y, adjustedY);
    mInputDriverEvent.setPressure(MotionEvent.AXIS_PRESSURE, 1.0f); // 设置压力值
    mInputDriverEvent.setContact(true);
    
    try {
        mInputDriver.emit(mInputDriverEvent);
    } catch (IOException e) {
        Log.e(TAG, "Failed to send touch down event", e);
    }
}

// 处理触摸移动事件
private void sendTouchMove(int rawX, int rawY) {
    int adjustedY = 480 - rawY;
    
    mInputDriverEvent.clear();
    mInputDriverEvent.setAction(MotionEvent.ACTION_MOVE);
    mInputDriverEvent.setPointerId(0);
    mInputDriverEvent.setPosition(MotionEvent.AXIS_X, rawX);
    mInputDriverEvent.setPosition(MotionEvent.AXIS_Y, adjustedY);
    mInputDriverEvent.setPressure(MotionEvent.AXIS_PRESSURE, 1.0f);
    mInputDriverEvent.setContact(true);
    
    try {
        mInputDriver.emit(mInputDriverEvent);
    } catch (IOException e) {
        Log.e(TAG, "Failed to send touch move event", e);
    }
}

// 处理触摸抬起事件
private void sendTouchUp() {
    mInputDriverEvent.clear();
    mInputDriverEvent.setAction(MotionEvent.ACTION_UP);
    mInputDriverEvent.setPointerId(0);
    mInputDriverEvent.setPressure(MotionEvent.AXIS_PRESSURE, 0.0f); // 压力置0
    mInputDriverEvent.setContact(false);
    
    try {
        mInputDriver.emit(mInputDriverEvent);
    } catch (IOException e) {
        Log.e(TAG, "Failed to send touch up event", e);
    }
}

3. 调用对应方法处理触摸状态

在获取到触摸坐标时,根据触摸的状态调用对应的方法:

// 假设你有触摸状态的判断逻辑
boolean isTouchDown = getTouchState(); // 自定义方法,判断是否处于触摸按下状态
int x = getTouchX();
int y = getTouchY();
// 记录上一次触摸状态,用于区分按下和移动
private boolean wasTouchDownBefore = false;

if (isTouchDown) {
    if (wasTouchDownBefore) {
        sendTouchMove(x, y);
    } else {
        sendTouchDown(x, y);
        wasTouchDownBefore = true;
    }
} else {
    if (wasTouchDownBefore) {
        sendTouchUp();
        wasTouchDownBefore = false;
    }
}

为什么这样能解决问题?

  • 动作类型:Android输入系统需要明确的ACTION_DOWN/MOVE/UP事件来区分触摸的不同阶段,没有这些类型,系统无法正确响应触摸操作。
  • 指针ID:用于区分多触摸场景,单触摸时设置为0即可,缺少它会导致事件无法被正确识别。
  • Y轴反转:大多数触摸板的坐标原点在左下角,而Android屏幕的原点在左上角,反转Y轴才能让触摸位置和屏幕光标对应。
  • 压力值:部分Android输入驱动要求触摸事件包含压力参数,否则会忽略该事件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:50:30