如何设置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
相关产品推荐
相关产品推荐

