Jetpack Compose:如何禁用儿童手势检测

use*_*569 19 gesture android-jetpack-compose

是否有一个内置函数Modifier可以禁用其子级的任何手势检测/指针输入交互?

例如

@Composable
fun Foo() {
    Box(modifier = Modifier.gesturesEnabled(enabled = false)) {
        BasicText(text = "Hello", modifier = Modifier.clickable { // clickable is not enabled
            // ...
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以使用以下方法来推出我自己的(非常简单)实现CompositionLocal

val LocalGesturesEnabled = compositionLocalOf { mutableStateOf(true) }

fun Modifier.myClickable(onClick: () -> Unit, enabled: Boolean = true) = composed {
    clickable(enabled = enabled && LocalGesturesEnabled.current.value, onClick)
}
Run Code Online (Sandbox Code Playgroud)

但它不适用于第三方可组合项或更复杂的可组合项(例如LazyList.

Phi*_*hov 38

我认为缺乏这样的系统修改器的原因是您必须通过使用启用/禁用控件的不同状态或使用半透明覆盖视图等向用户显示手势已被禁用。

但从技术上讲,使用pointerInput修饰符您可以获取所有触摸事件awaitPointerEvent

使用该pass = PointerEventPass.Initial参数,您将在所有子视图之前接收事件,然后您可以将事件标记为已处理consumeAllChanges,以便子视图将不再接收它们。

fun Modifier.gesturesDisabled(disabled: Boolean = true) =
    if (disabled) {
        pointerInput(Unit) {
            awaitPointerEventScope {
                // we should wait for all new pointer events
                while (true) {
                    awaitPointerEvent(pass = PointerEventPass.Initial)
                        .changes
                        .forEach(PointerInputChange::consume)
                }
            }
        }
    } else {
        this
    }
Run Code Online (Sandbox Code Playgroud)

如果您想了解有关自定义手势处理的更多信息,请查看这篇文章

  • 如果未禁用,您是否宁愿返回“this”而不是“Modifier”,以免在调用站点进一步丢失所有先前设置的修饰符更改? (2认同)