Jetpack Compose 如何阻止底部表单聚焦元素抢占系统返回键处理逻辑
问题根因
Compose的返回事件分发遵循优先级从高到低规则,输入框等聚焦元素的返回清除焦点逻辑优先级高于默认BackHandler,所以首次按下返回键时事件会被焦点逻辑优先消费,只有焦点清除后第二次按下返回才会触发你写的BackHandler逻辑。
解决方案
直接为底部表单的根布局添加键盘按键监听,优先级高于内置的焦点返回处理,拦截返回键事件直接执行收起逻辑:
import android.view.KeyEvent import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material3.BottomSheet import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.ui.Modifier import androidx.compose.ui.input.key.onKeyEvent import androidx.compose.ui.platform.LocalFocusManager import kotlinx.coroutines.launch // 你的底部表单实现处 val focusManager = LocalFocusManager.current val scope = rememberCoroutineScope() @OptIn(ExperimentalMaterial3Api::class) BottomSheet( sheetState = bottomSheetState, onDismissRequest = { /* 你的收起逻辑 */ } ) { Column( modifier = Modifier .fillMaxWidth() // 优先拦截返回键事件 .onKeyEvent { keyEvent -> if ( keyEvent.nativeKeyEvent.keyCode == KeyEvent.KEYCODE_BACK && bottomSheetState.isExpanded && keyEvent.nativeKeyEvent.action == KeyEvent.ACTION_UP // 只响应按键抬起事件,避免重复触发 ) { scope.launch { focusManager.clearFocus() bottomSheetState.collapse() } // 返回true表示事件已被消费,不会向下分发给焦点处理逻辑 true } else { false } } ) { // 底部表单内部内容,包括TextField等聚焦元素 } }
如果需要保留原有BackHandler的写法,也可以改用更高优先级的返回回调注册方式:通过LocalOnBackPressedDispatcherOwner获取返回分发器,手动注册优先级最高的回调,在底部表单展开时拦截所有返回事件。
内容的提问来源于stack exchange,提问作者Carter Hudson
相关产品推荐
相关产品推荐

