android - 拒绝外设触摸输入

标签 android android-layout

给定一个嵌套的 View 结构,例如:

Nested app layout

我如何禁用灰色外围的输入,这样即使用户将手指放在上面,但触摸了黄色 View ,触摸事件也会在该 View 的 dispatchTouchEvent() 中注册畅通无阻?

编辑: 为了进一步解释,我需要在灰色区域使用某种防手掌误触系统。在黄色区域,用户可以用手指画画。所有这些都工作正常,但在一些配备无边框显示屏的手机上,您可能会不小心触摸到灰色区域,该区域会注册为输入并且绘图会被破坏。

只有当用户同时在多个地方触摸屏幕时才会发生这种情况。在这一点上,有人可能会责怪用户购买了这个噱头,但我自己已经尝试过了,很容易不小心碰到边缘,并阻止事件正常流动。

在我发布这个问题之后,我想出了一个使用多点触控事件的有点老套的解决方案。它比以前工作得更好,但因为它不是真正的多点触控事件,有时它会变得陈旧并完全停止注册输入。此外,如果最终能够在黄色框中捕获真实的多点触摸事件(例如放大您的绘图手势),那就太好了。

到目前为止,我的解决方案的基本前提是:

  1. 设置 View 。在这个测试用例中,我只有一个 View ,它在其 onDraw() 中绘制了所有区域。
  2. dispatchTouchEvent() 中捕获 MotionEvent
  3. 挑出黄色区域内 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/

相关文章:

android - ListActivity getView - 进度条或在后台执行?

android - 如何将KML文件插入android mapview?

android - 按钮上的单选按钮文本

android - 单击编辑文本时如何向上滚动布局

android - Android 中的自定义键盘键宽

android - 使用 AppCompat 获取 NullPointerException

android - 在 Android 项目上实现 DAO 模式

java - 我可以使用 Jar 签名来保护 Android APK 文件免遭反编译吗?

android - 如何取消withContext中运行的协程?

android - android (android.R.drawable.{checkbox}) 中 Material Design 复选框的名称是什么?