Jetpack Compose中没有焦点的OnKeyEvent

3

我正在创建一个应用程序,使用设备上的物理按钮。

这个按钮的功能会根据活动屏幕不同而有所不同。

对于活动屏幕,我通常会为每个屏幕创建一个活动,并在每个屏幕中覆盖onKeyDown函数。那么如何在单个活动中实现这一点,以在不同的Jetpack Compose屏幕之间导航呢?根据Android文档,正确的方法是像这样...

Box(modifier = Modifier
    .onKeyEvent {
        Log.e("Pressed", it.nativeKeyEvent.keyCode.toString())
        true
    }
    .focusable()
    .fillMaxSize()
    .background(Color.Gray)
) {
    // All screen components
}

但这仅在屏幕上的一个元素被聚焦时才起作用,我需要的是始终如此,是否有方法实现?

1个回答

6

一种选择是保持焦点在视图上,这样Modifier.onKeyEvent总是起作用。请注意,它可能与其他可聚焦的视图(如TextField)发生冲突,因此所有这些视图都应该是这个始终可聚焦视图的子级(可以在任何层级)。

val focusRequester = remember { FocusRequester() }
var hasFocus by remember { mutableStateOf(false) }
Box(
    Modifier
        .focusRequester(focusRequester)
        .onFocusChanged {
            hasFocus = it.hasFocus
        }
        .focusable()
        .onKeyEvent {
            TODO()
        }
) {
}
if (!hasFocus) {
    LaunchedEffect(Unit) {
        focusRequester.requestFocus()
    }
}

另一种选择是创建组合本地处理程序并从您的活动传递事件:

class MainActivity : AppCompatActivity() {
    private val keyEventHandlers = mutableListOf<KeyEventHandler>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            CompositionLocalProvider(LocalKeyEventHandlers provides keyEventHandlers) {
                // your app
            }
        }
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
        return keyEventHandlers.reversed().any { it(keyCode, event) } || super.onKeyDown(keyCode, event)
    }
}

val LocalKeyEventHandlers = compositionLocalOf<MutableList<KeyEventHandler>> {
    error("LocalKeyEventHandlers is not provided")
}

typealias KeyEventHandler = (Int, KeyEvent) -> Boolean

@Composable
fun ListenKeyEvents(handler: KeyEventHandler) {
    val handlerState = rememberUpdatedState(handler)
    val eventHandlers = LocalKeyEventHandlers.current
    DisposableEffect(handlerState) {
        val localHandler: KeyEventHandler = {
            handlerState.value(it)
        }
        eventHandlers.add(localHandler)
        onDispose {
            eventHandlers.remove(localHandler)
        }
    }
}

使用:

ListenKeyEvents { code, event ->
    TODO()
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接