Wear OS Compose导航切换后Rotary Input无法正常工作
针对你遇到的旋转表冠(Rotary Input)在导航后失效的问题,核心原因是导航过程中焦点没有正确绑定到目标页面的ScalingLazyColumn,导致系统发出的旋转事件无人消费(对应日志里的“Rotary event created but not consumed”)。以下是具体的排查和解决步骤:
1. 确保页面重组时主动请求焦点
你已经用了FocusRequester,但可能只在页面首次初始化时请求了焦点,导航回来或进入新页面时没有重新触发。需要配合LaunchedEffect,在页面每次重组(包括导航切换后)时主动请求焦点:
@Composable fun SettingsScreen() { val focusRequester = remember { FocusRequester() } val currentRoute = currentBackStackEntryAsState().value?.destination?.route Scaffold { padding -> ScalingLazyColumn( modifier = Modifier .fillMaxSize() .padding(padding) .focusRequester(focusRequester) .focusable(), // 其他配置 ) { // 列表项内容 } } // 当路由切换到当前页面时,请求焦点 LaunchedEffect(currentRoute) { if (currentRoute == "settings") { focusRequester.requestFocus() } } }
主页面也需要同样处理,确保返回主屏幕时重新获取焦点。
2. 排除Scaffold其他组件的焦点干扰
检查Scaffold的topBar、bottomBar等组件,如果这些区域包含可焦点元素(比如按钮、文本输入框),可能会抢占ScalingLazyColumn的焦点。对于不需要交互的顶部/底部栏,直接设置focusable(false):
Scaffold( topBar = { TopAppBar( title = { Text("设置") }, modifier = Modifier.focusable(false) ) } ) { // 页面内容 }
3. 验证焦点状态
可以通过LocalFocusManager打印当前焦点所在组件,确认导航前后焦点是否正确落在ScalingLazyColumn上:
val focusManager = LocalFocusManager.current LaunchedEffect(currentRoute) { // 打印焦点节点信息,排查焦点去向 println("当前焦点组件: ${focusManager.focusedChild}") }
4. 升级Wear Compose依赖
部分旧版本的Wear Compose在SwipeDismissableNavHost的焦点管理上存在bug,建议升级到最新稳定版(比如1.2.1及以上),可能直接解决此类兼容性问题。
总结
旋转表冠依赖组件焦点才能消费事件,导航切换时必须确保目标页面的ScalingLazyColumn在重组完成后主动获取焦点,同时避免其他组件抢占焦点。按照上述步骤调整后,应该能解决导航后旋转表冠失效的问题。
内容的提问来源于stack exchange,提问作者amoledwatchfaces

