Estoy creando una aplicación que utiliza un botón físico en el dispositivo.
Este botón tendrá una funcionalidad diferente dependiendo de la pantalla que esté activa.
Con Actividades lo que haría sería tener una Actividad para cada pantalla y en cada una anularía la función onKeyDown. ¿Cómo haría esto con una sola actividad que navega entre diferentes pantallas de Jetpack Compose? De acuerdo con la documentación de Android, la forma correcta sería algo como esto...
Box(modifier = Modifier .onKeyEvent { Log.e("Pressed", it.nativeKeyEvent.keyCode.toString()) true } .focusable() .fillMaxSize() .background(Color.Gray) ) { // All screen components }Pero esto solo funciona cuando uno de los elementos de la pantalla esta enfocado y lo que requiero es que siempre funcione o no, hay alguna forma de lograrlo?
Una opción es mantener el foco en la vista para que Modifier.onKeyEvent siempre funcione. Tenga en cuenta que puede entrar en conflicto con otras vistas enfocables, como TextField , por lo que todas estas vistas deben ser elementos secundarios (en cualquier nivel) de esta vista siempre enfocable.
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() } }Otra opción es crear controladores locales de composición y pasar eventos de su actividad:
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 eventHandlers = LocalKeyEventHandlers.current DisposableEffect(handler) { eventHandlers.add(handler) onDispose { eventHandlers.remove(handler) } } }Uso:
ListenKeyEvents { code, event -> TODO() }