我需要有两种不同的行为,一种用于D-pad,另一种用于模拟游戏杆(在同一游戏板上)。
问题是在onGenericMotionEvent
回调上,两者在MotionEvent
上都具有相同的信息,而我无法区分它们。
// d-pad
MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=-1.5259255E-5, y[0]=-1.5259255E-5, toolType[0]=TOOL_TYPE_UNKNOWN, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=151637936, downTime=0, deviceId=5, source=0x1000010 }
// analog joystick
MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=0.64507514, y[0]=0.710811, toolType[0]=TOOL_TYPE_UNKNOWN, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=151650802, downTime=0, deviceId=5, source=0x1000010 }
是否可以确定正在使用哪种输入?如何?
最佳答案
我遇到了同样的问题,我不得不仔细研究this helpful Git user's project以弄清楚他是如何做到的。区分不同操纵杆(和D-pad)的方法是使用每个方向的特定轴。
如果您非常仔细地阅读了Android documentation's page(我没有读过),它的确显示了如何区分各种操纵杆及其方向:
此图显示左操纵杆使用 AXIS_X 和轴AXIS_Y ,而右操纵杆使用 AXIS_Z 和 AXIS_RZ 。对于D-pad,我使用了 AXIS_HAT_X 和 AXIS_HAT_Y 。我的代码中的以下代码段(在Kotlin中)显示了如何分别访问每个代码:
注意:我的搜索栏也设置为0-100,这就是为什么在processJoystickInput()
的底部设置了转换数学的原因。
private fun processJoystickInput(event: MotionEvent, historyPos: Int) {
val inputDevice = event.device
val newJoystickValues = floatArrayOf(
getCenteredAxis(event, inputDevice, MotionEvent.AXIS_X, historyPos),
getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Y, historyPos),
getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Z, historyPos),
getCenteredAxis(event, inputDevice, MotionEvent.AXIS_RZ, historyPos),
getCenteredAxis(event, inputDevice, MotionEvent.AXIS_HAT_X, historyPos),
getCenteredAxis(event, inputDevice, MotionEvent.AXIS_HAT_Y, historyPos))
// Update based on the new x and y values
val throttleSeekBar = findViewById<SeekBar>(R.id.throttle_seekBar)
val yawSeekBar = findViewById<SeekBar>(R.id.yaw_seekBar)
val pitchSeekBar = findViewById<SeekBar>(R.id.pitch_seekBar)
val rollSeekBar = findViewById<SeekBar>(R.id.roll_seekBar)
val dpadXSeekBar = findViewById<SeekBar>(R.id.dpadX_seekBar)
val dpadYSeekBar = findViewById<SeekBar>(R.id.dpadY_seekBar)
// Convert the float range (-1.00 to 1.00) to Int (0 to 100)
yawSeekBar.progress = ((newJoystickValues[0] + 1) * 50).toInt()
throttleSeekBar.progress = ((newJoystickValues[1] + 1) * 50).toInt()
rollSeekBar.progress = ((newJoystickValues[2] + 1) * 50).toInt()
pitchSeekBar.progress = ((newJoystickValues[3] + 1) * 50).toInt()
dpadXSeekBar.progress = ((newJoystickValues[4] + 1) * 50).toInt()
dpadYSeekBar.progress = ((newJoystickValues[5] + 1) * 50).toInt()
}
override fun onGenericMotionEvent(event: MotionEvent): Boolean {
// Check that the event came from a game controller
return if (event.source and(InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK
&& event.action == MotionEvent.ACTION_MOVE) {
// Process the movements starting from the
// earliest historical position in the batch
(0 until event.historySize).forEach { i ->
// Process the event at historical position i
processJoystickInput(event, i)
}
// Process the current movement sample in the batch (position -1)
processJoystickInput(event, -1)
true
} else {
super.onGenericMotionEvent(event)
}
}