Вопрос или проблема
Я в настоящее время пытаюсь реализовать предсказательное возвращение в своем приложении и столкнулся с ошибкой.
Похоже, что это ошибка Android 14 или Samsung OS. Условия возникновения ошибки следующие:
- предсказательное возвращение включено
- пользователь находится на экране фрагмента диалога с редактируемым текстом
- редактируемый текст имеет фокус и находится в режиме “выбор текста” (курсор имеет форму капли вместо вертикальной линии)
Если пользователь медленно инициирует жест возвращения, предсказательное возвращение срабатывает, но затем зависает. Событие отмены не вызывается (handleOnBackCancelled()
не вызывается).
Мне удалось воспроизвести эту ошибку на S24 с последними обновлениями (Android 14), однако я не смог воспроизвести эту ошибку на Pixel 7 с последними обновлениями (также Android 14). Я знаю, что линейка Pixel получила 2 специфических патча ОС, поэтому возможно, что Pixel 7 получил исправление, в то время как Samsung OS не получил это исправление. Однако я не исключаю возможность того, что это специфическая ошибка Samsung.
Если кто-то знает причину или обходной путь, дайте знать.
Эта ошибка, похоже, является ошибкой Android 14 ИЛИ ошибкой Samsung OS. У меня нет устройства на Android 14, не относящегося к Pixel и Samsung, чтобы подтвердить.
Я смог придумать обходной путь, так как маловероятно, что есть решение проблемы, кроме как просто обновить ОС.
Обходной путь заключается в том, чтобы убрать состояние, при котором EditText имеет фокус, но клавиатура не отображается. Насколько я могу судить, устранение этого состояния не ухудшает пользовательский опыт.
Я сделал это, установив слушатель видимости клавиатуры следующим образом:
class MyDialogFragment : DialogFragment() {
...
private val isKeyboardHiddenState = MutableStateFlow(true)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, windowInsets ->
val imeInset = windowInsets.getInsets(WindowInsetsCompat.Type.ime())
isKeyboardHiddenState.value = imeInset.bottom == 0
WindowInsetsCompat.CONSUMED
}
viewLifecycleOwner.lifecycleScope.launch {
isKeyboardHiddenState.collect { isKeyboardHidden ->
if (isKeyboardHidden && myEditText.isFocused) {
myEditText.clearFocus()
}
}
}
}
}
Ответ или решение
Проблема с предсказательным возвратом в Android 14: Решение и обходные пути
Введение
В последнее время многие разработчики сталкиваются с проблемами при реализации функций предсказательного возврата в Android-приложениях. В данной статье мы обсудим специфическую проблему, связанную с фокусировкой на элементах ввода, в частности с EditText
, во время активации предсказательного возврата на устройствах с ОС Android 14, особенно на устройствах Samsung.
Описание проблемы
Проблема возникает при следующих условиях:
- Функция предсказательного возврата включена.
- Пользователь находится на экране диалогового фрагмента, содержащем
EditText
. EditText
имеет фокус, и курсор находится в режиме "выбора текста" (в виде капли).
При медленной инициации жеста возврата предсказательный возврат срабатывает, но затем процесс зависает. Важно отметить, что ни одно событие отмены не срабатывает (метод handleOnBackCancelled()
не вызывается).
Поведение на различных устройствах
Данная проблема была воспроизведена на Samsung Galaxy S24 с последними обновлениями (Android 14), но не была воспроизведена на Google Pixel 7 с аналогичными обновлениями. Это указывает на возможный патч в Pixel 7, который, возможно, еще не был включен в устройство Samsung, либо на наличие уникальной проблемы в прошивке Samsung.
Временное решение
Как временное решение можно попробовать использовать обходной путь с использованием слушателя для определения видимости клавиатуры. Если клавиатура скрыта и EditText
имеет фокус, можно снять фокус с EditText
, что, по сути, устраняет состояние, вызывающее проблему. Этот подход не ухудшает пользовательский опыт.
Вот пример кода, который реализует данное решение:
class MyDialogFragment : DialogFragment() {
...
private val isKeyboardHiddenState = MutableStateFlow(true)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view)
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, windowInsets ->
val imeInset = windowInsets.getInsets(WindowInsetsCompat.Type.ime())
isKeyboardHiddenState.value = imeInset.bottom == 0
WindowInsetsCompat.CONSUMED
}
viewLifecycleOwner.lifecycleScope.launch {
isKeyboardHiddenState.collect { isKeyboardHidden ->
if (isKeyboardHidden && myEditText.isFocused) {
myEditText.clearFocus()
}
}
}
}
}
Заключение
Описанная проблема с предсказательным возвратом на Android 14 с акцентом на устройствах Samsung представляет собой довольно серьезный баг, требующий внимания. Хотя временное решение уменьшает возможность зависания, желательно следить за обновлениями системы от Samsung и Google для окончательного изменения поведения.
Если вы столкнулись с подобной проблемой, не стесняйтесь делиться своим опытом и решениями, чтобы помочь сообществу разработчиков.