我正在尝试在一个带有Compose UI的Android应用中隐藏软键盘。ViewModel通过kotlin协程通道发出了一些事件:
private val _screenEvents = Channel<ScreenEvent>(capacity = Channel.UNLIMITED)
val screenEvents: Flow<ScreenEvent> = _screenEvents.receiveAsFlow()
事件按如下方式发送:
_screenEvents.trySend(event)
在"编写"屏幕中,事件收集在LaunchedEffect中,任何隐藏键盘的方法都只起作用一次,不会收集连续事件。
val keyboard = LocalSoftwareKeyboardController.current
val inputService = LocalTextInputService.current
val focusManager = LocalFocusManager.current
LaunchedEffect(Unit) {
viewModel.screenEvents
.collect { event ->
when (event) {
is ScreenEvent.CollapseSearchResults -> {
// keyboard?.hide()
// inputService?.hideSoftwareKeyboard()
focusManager.clearFocus()
bottomSheetState.collapse()
}
...
}
}
}
TextField(value = "") {}
但如果我把这两行换一下
bottomSheetState.collapse()
// keyboard?.hide()
// inputService?.hideSoftwareKeyboard()
focusManager.clearFocus()
每件事都工作正常,因为许多倍的必要。但动画折叠底部表和隐藏键盘是连续的,它不适合我。
有人能给我解释一下问题是什么,我如何解决它?
编辑
如果UI中的TextField具有焦点并且显示软键盘,则会产生此问题。如果用户在BottomSheet处于动画状态时按住BottomSheet,也会产生此问题。结果发现BottomSheet动画是可取消的,并且在这种情况下会抛出CancellationException。
最小、完整、可重现示例:https://gist.github.com/Alektas/e86e75a596cb20797f5c9acac238e24f
3条答案
按热度按时间31moq8wy1#
事实证明,
BottomSheet
动画是可取消的,并且当FocusManager
从TextField
清除焦点时抛出CancellationException
作为一个变通方案,我现在用
try/catch
来 Package 崩溃。如果有人能给出更好的解决这个问题的方法,我会很高兴的。emeijp432#
目前,FlowCollector -
bottomSheetState.collapse
在LaunchedEffect
作用域中启动。因此,当折叠流收集器中发生异常时,LaunchedEffect
作用域将被停用。按如下所示尝试
Composition CoroutineScope
。u0njafvf3#
这是更多关于re-composition它似乎,每当你的状态改变composer函数开始recomposition,
LaunchEffect
coroutineContext
将被取消和你的底部工作表显示/隐藏将得到中断.要解决这个问题,你可以尝试NonCancelable Job像下面这里是参考链接运行不可取消的块