给定一个嵌套的 View 结构,例如:
我如何禁用灰色外围的输入,这样即使用户将手指放在上面,但触摸了黄色 View ,触摸事件也会在该 View 的 dispatchTouchEvent()
中注册畅通无阻?
编辑: 为了进一步解释,我需要在灰色区域使用某种防手掌误触系统。在黄色区域,用户可以用手指画画。所有这些都工作正常,但在一些配备无边框显示屏的手机上,您可能会不小心触摸到灰色区域,该区域会注册为输入并且绘图会被破坏。
只有当用户同时在多个地方触摸屏幕时才会发生这种情况。在这一点上,有人可能会责怪用户购买了这个噱头,但我自己已经尝试过了,很容易不小心碰到边缘,并阻止事件正常流动。
在我发布这个问题之后,我想出了一个使用多点触控事件的有点老套的解决方案。它比以前工作得更好,但因为它不是真正的多点触控事件,有时它会变得陈旧并完全停止注册输入。此外,如果最终能够在黄色框中捕获真实的多点触摸事件(例如放大您的绘图手势),那就太好了。
到目前为止,我的解决方案的基本前提是:
- 设置 View 。在这个测试用例中,我只有一个 View ,它在其
onDraw()
中绘制了所有区域。 - 在
dispatchTouchEvent()
中捕获MotionEvent
- 挑出黄色区域内 x,y 的事件部分:
然后:
// ... event:MotionEvent, pointerCoordsOut:MotionEvent.PointerCoords
for (pidx in 0 until event.pointerCount) {
event.getPointerCoords(pidx, pointerCoordsOut)
if (inYellowArea(pointerCoordsOut.x, pointerCoordsOut.y)) {
//pointerCoordsOut now has (x,y) that I need
}
}
最后,调整代码接受ACTION_*
和ACTION_POINTER_*
事件,让它们做一些合理的事情。这在演示案例中非常简单,但我认为这是解决方案最终会失败的地方。
所以我仍然希望有一个适当的解决方案来解决边界上的手掌拒绝问题,就好像那个事件根本不存在一样,而不是在我的情况下是复杂手势的一部分我正在尝试破译。
编辑:
仍然欢迎建议。
最佳答案
更新:
布局:
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/darker_gray"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/orange"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="64dp"
android:layout_marginEnd="64dp"
android:layout_marginStart="64dp"
android:layout_marginTop="64dp"
android:background="@android:color/holo_orange_dark"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
代码:
class MainActivity : AppCompatActivity() {
private val touchableRect = Rect()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
root.post {
orange.getGlobalVisibleRect(touchableRect)
}
root.setOnTouchListener { v, event ->
Log.d("logi", "root touched : ${event.actionMasked}")
false
}
orange.setOnTouchListener { v, event ->
Log.d("logi", "orange touched : ${event.actionMasked}")
true
}
}
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
val isConsumed = ev?.let {
if (touchableRect.contains(it.x.toInt(), it.y.toInt())) {
orange.dispatchTouchEvent(it)
} else {
true
}
}
return isConsumed ?: true
}
}
关于android - 拒绝外设触摸输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54589194/