Ger*_*ruz 3 android kotlin android-jetpack-navigation android-jetpack-compose
我正在创建一个使用设备上的物理按钮的应用程序。
根据活动屏幕的不同,此按钮将具有不同的功能。
对于“活动”,我要做的就是为每个屏幕创建一个“活动”,并在每个屏幕中重写 onKeyDown 函数。如何通过在不同 Jetpack Compose 屏幕之间导航的单个 Activity 来实现此目的?根据Android文档,正确的方法是这样的......
Box(modifier = Modifier
.onKeyEvent {
Log.e("Pressed", it.nativeKeyEvent.keyCode.toString())
true
}
.focusable()
.fillMaxSize()
.background(Color.Gray)
) {
// All screen components
}
Run Code Online (Sandbox Code Playgroud)
但这仅在屏幕上的一个元素聚焦时才有效,而我要求的是它始终有效或无效,有没有办法实现这一点?
一种选择是将焦点保持在视图上,以便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()
}
}
Run Code Online (Sandbox Code Playgroud)
另一种选择是创建组合本地处理程序并从您的活动传递事件:
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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
ListenKeyEvents { code, event ->
TODO()
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1924 次 |
| 最近记录: |