Или как скрыть нижний компонент навигации с помощью WindowInsetsCompat

Внедрить UX-потоки с нижней навигацией и экранной клавиатурой на Android должно быть легко. Но, как большинство из вас уже знает, это не так. Нижняя панель навигации занимает много места внизу экрана. Когда клавиатура недоступна, это не проблема, и все в порядке. Но когда появляется экранная клавиатура, она занимает еще больше места в нижней части экрана, а если она отображается сразу с навигацией, места для любого содержания не остается. Поэтому мы хотим и должны перекрыть нижнюю навигацию с клавиатурой и отображать только контент.

Определение атрибута windowSoftInputMode в AndroidManifest.xml предоставляет нам два варианта, adjustPan и adjustResize, для обеспечения доступности контента на- экран и, может быть, под самой клавиатурой. Это старая тема, и вы уже найдете на нее хорошие статьи, поэтому я не буду вдаваться в подробности об этих двух вариантах. Для меня adjustPan никогда не было достаточно, поэтому я всегда выбираю adjustResize, чтобы получить немного больше контроля над содержимым и его поведением при открытии клавиатуры. Но само по себе это еще не скрывает нижнюю навигацию.

Начиная с Android API уровня 30, WindowInsets.Type.ime() можно использовать для получения информации независимо от того, отображается ли экранная клавиатура. При использовании WindowInsetsCompat.isVisible() ( доступно с androidx.core 1.5.0) эта информация также доступна с уровнем API 29 и ниже ( в настоящее время до уровня API 23 ). Чтобы скрыть mainNavigation вашего MainActivity, вам нужно всего лишь установить OnApplyInsetsListener, чтобы реагировать на изменения во вставках.

window.decorView.setOnApplyWindowInsetsListener { view, insets ->
    val insetsCompat = toWindowInsetsCompat(insets, view)
    mainNavigation.isGone = insetsCompat.isVisible(ime())
    view.onApplyWindowInsets(insets)
}

В той же области вы можете автоматически скрыть экранную клавиатуру, когда метод ввода не требуется. Это в основном тот случай, когда текущее сфокусированное представление - это что-то иное, кроме EditText или любого дочернего типа. Вам нужно только реализовать OnGlobalFocusChangeListener с условным оператором скрытия.

window.decorView.viewTreeObserver.addOnGlobalFocusChangeListener { oldView, newView ->
    if (newView !is EditText) imm.hideSoftInputFromWindow(
        (oldView ?: newView)?.windowToken
            ?: window.attributes.token,
        0 // or HIDE_IMPLICIT_ONLY
    )
}

С обоими слушателями вместе вы сможете обрабатывать все соответствующие изменения экранной клавиатуры в пределах вашего MainActivity или основного экрана, содержащего BottomNavigation представление.

Для этого я создал крошечную и простую утилиту в Kotlin для предоставления функций расширения hideKeyboardOnFocusChange() и setOnKeyboardVisibilityChangeListener()