拒绝外围触摸输入

Gle*_*eno 8 android android-layout

给定嵌套视图结构,例如:

嵌套的应用布局

如何禁用灰色边缘上的输入,这样即使用户手指握住它,但触摸黄色视图,触摸事件也会无dispatchTouchEvent()阻碍地注册该视图?

编辑:为了进一步解释,我需要灰色区域的某种手掌剔除系统.在黄色区域中,用户可以用他的手指绘制.所有这些都可以正常工作,但在某些带无边框显示屏的手机上,您可能会意外触摸灰色区域,灰色区域会记录为输入并且图形会被破坏.

仅当用户同时在多个位置触摸屏幕时才会发生这种情况.在这一点上,人们可能会责怪用户购买噱头,但我自己也尝试过,并且很容易意外碰到边缘,并防止事件正常流动.

在我发布这个问题之后,我想出了一个使用多点触控事件的有点hacky解决方案.它比以前工作得更好,但因为它不是真正的多点触摸事件,有时它会过时并停止完全注册输入.此外,最终能够在黄色框中捕获真实的多点触摸事件(例如,进行放大 - 绘制手势)将会很棒.

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

  1. 设置视图.在这个测试用例中,我只有一个View,它绘制了它的所有区域onDraw().
  2. 捕获MotionEventdispatchTouchEvent()
  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
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,调整代码以接受ACTION_*ACTION_POINTER_*事件,并让他们做一些合理的事情.这在演示案例中很容易,但我认为这是解决方案最终会失败的地方.

因此,我仍然希望有一个适当的解决方案,以便在边界上进行手掌拒绝 - 如果该事件根本不存在,而不是在我的情况下,我试图破译的复杂手势的一部分.

编辑:

仍然愿意接受建议.

kov*_*777 3

更新:
布局:

<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>
Run Code Online (Sandbox Code Playgroud)

代码:

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
    }
}
Run Code Online (Sandbox Code Playgroud)