Jetpack Compose - не дать сфокусированным элементам украсть пресс?
У меня есть некоторые элементы, которые находятся в фокусе на нижнем листе. Я хочу свернуть нижний лист при нажатии кнопки возврата системы, что достаточно просто:
BackHandler(enabled = bottomSheetState.isExpanded) {
scope.launch {
bottomSheetState.collapse()
}
}
Проблема в том, что если элемент сфокусирован на нижнем листе, логика обратного обработчика запускается только после двойного нажатия кнопки возврата : один раз для удаления фокуса с элемента (выделенное текстовое поле) и еще раз для запуска коллапса.
Я пробовал использовать
LocalFocusManager.current
чтобы объединить очистку фокуса при нажатии кнопки возврата, но логика возврата не запускается, пока элемент уже не потерял фокус.
Я могу убрать фокус при свертывании, поэтому я предполагаю, что настоящая проблема заключается в том, чтобы дважды нажать назад, когда лист 1) виден и 2) имеет сфокусированный дочерний элемент.
Есть ли способ, чтобы сфокусированные элементы не вытесняли мою обратную логику?
1 ответ
Привет, @Carter. Я обнаружил проблему на официальном трекере. Ссылку найти можноздесь . Это было исправлено в compose 1.1.0-alpha03, но поскольку библиотека является альфа-кандидатом, я не знаю, насколько она безопасна для производства. Существует также обходной путь упоминается здесь
более чистый подход:
- Создать этого менеджера
/***
* Compose issue to be fixed in alpha 1.03
* track from here : https://issuetracker.google.com/issues/192433071?pli=1
* current work around
*/
class KeyBoardManager(context: Context) {
private val activity = context as Activity
private var keyboardDismissListener: KeyboardDismissListener? = null
private abstract class KeyboardDismissListener(
private val rootView: View,
private val onKeyboardDismiss: () -> Unit
) : ViewTreeObserver.OnGlobalLayoutListener {
private var isKeyboardClosed: Boolean = false
override fun onGlobalLayout() {
val r = Rect()
rootView.getWindowVisibleDisplayFrame(r)
val screenHeight = rootView.rootView.height
val keypadHeight = screenHeight - r.bottom
if (keypadHeight > screenHeight * 0.15) {
// 0.15 ratio is right enough to determine keypad height.
isKeyboardClosed = false
} else if (!isKeyboardClosed) {
isKeyboardClosed = true
onKeyboardDismiss.invoke()
}
}
}
fun attachKeyboardDismissListener(onKeyboardDismiss: () -> Unit) {
val rootView = activity.findViewById<View>(android.R.id.content)
keyboardDismissListener = object : KeyboardDismissListener(rootView, onKeyboardDismiss) {}
keyboardDismissListener?.let {
rootView.viewTreeObserver.addOnGlobalLayoutListener(it)
}
}
fun release() {
val rootView = activity.findViewById<View>(android.R.id.content)
keyboardDismissListener?.let {
rootView.viewTreeObserver.removeOnGlobalLayoutListener(it)
}
keyboardDismissListener = null
}
}
- Создать этот составной
@Composable
fun AppKeyboardFocusManager() {
val context = LocalContext.current
val focusManager = LocalFocusManager.current
DisposableEffect(key1 = context) {
val keyboardManager = KeyBoardManager(context)
keyboardManager.attachKeyboardDismissListener {
focusManager.clearFocus()
}
onDispose {
keyboardManager.release()
}
}
}
- Подать заявку на уровне приложения
setContent {
AppKeyboardFocusManager()
YourAppMaterialTheme {
...
}
}