В наших предыдущих статьях мы обсуждали устаревание метода onBackPressed и появление onBackPressedDispatcher в библиотеке Android Jetpack Compose. По мере того, как мы продолжаем изучать новые функции и изменения в Jetpack Compose, важно понимать, как справляться с нажатиями в обратном направлении из непосредственно компонуемых объектов. В этой статье мы углубимся в детали того, как обрабатывать обратное нажатие из непосредственно компонуемых объектов, и предложим обходной путь для нового OnBackInvokedCallback. Независимо от того, являетесь ли вы опытным разработчиком Android или только начинаете работать с Jetpack Compose, эта статья предоставит ценную информацию и методы управления нажатиями на кнопку в компонуемом пользовательском интерфейсе.

Прежде всего, мы начнем с того, как обращаться с обратными нажатиями в составных. Как вы, возможно, знаете, у нас есть OnBackPressedCallback, который используется для получения обратных вызовов обратных нажатий. Обратный вызов

Прежде всего, мы начнем с того, как обращаться с обратными нажатиями в составных. Как вы, возможно, знаете, у нас есть OnBackPressedCallback, который используется для получения обратных вызовов обратных нажатий. Обратный вызов принимает логический параметр, который сообщает, обрабатывается ли обратное нажатие или нет, и лямбда, которая вызывается, когда обрабатывается обратное нажатие. Вот простой пример того, как его создать.

object : OnBackPressedCallback(true) {
    override fun handleOnBackPressed() {
        Log.d("TAG", "OnBackPressed")
    }
}

В compose у нас есть аналогичная функция BackHandler. По сути, это компонуемый объект, который принимает лямбду, которая вызывается при обработке обратного нажатия. Компонуемый BackHandler использует OnBackPressedCallback для внутреннего использования. Он добавляет и удаляет обратный вызов, когда компонуемый добавляется и удаляется из композиции соответственно. Здесь вы можете увидеть, как его использовать.

BackHandler(true) {
    Log.d("TAG", "OnBackPressed")
}

Обратите внимание, что из-за того, что функция использует OnBackPressedCallback внутри, она будет блокировать и потреблять предстоящие обратные нажатия. Таким образом, если владелец жизненного цикла использует свой собственный OnBackPressedCallback, он не будет вызываться.

Теперь давайте посмотрим, как обрабатывать OnBackInvokedCallback в compose.

Напомним, что OnBackInvokedCallback используется для прогнозирующего жеста назад. Он сообщает ОС, что приложение обработало жест «назад», и ОС не должна показывать подсказку о жесте «назад». Прежде чем идти дальше, давайте включим обратный вызов в приложении. Для этого нам нужно добавить следующую строку в файл манифеста.

android:enableOnBackInvokedCallback="true"

Не забудьте включить интеллектуальные жесты назад на устройстве Android 13 или более поздней версии. В противном случае обратный вызов не будет вызван.

К сожалению, нет прямого способа использовать обратный вызов в compose. Но я написал простой компонуемый, который использует OnBackInvokedCallback внутри и вызывает OnBackInvokedCallback при обработке обратного нажатия. Так же, как BackHandler. Вот код.

@Composable
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
fun BackInvokeHandler(
    handleBackHandler: Boolean,
    priority : Int = OnBackInvokedDispatcher.PRIORITY_DEFAULT,
    callback : () -> Unit = {}
) {
    val backInvokedCallback = remember {
        OnBackInvokedCallback {
            callback()
        }
    }

    val activity = when(LocalLifecycleOwner.current) {
        is MainActivity -> LocalLifecycleOwner.current as MainActivity
        is Fragment -> (LocalLifecycleOwner.current as Fragment).requireActivity() as MainActivity
        else -> {
            val context = LocalContext.current
            if (context is MainActivity) {
                context
            } else {
                throw IllegalStateException("LocalLifecycleOwner is not MainActivity or Fragment")
            }
        }
    }

    if (handleBackHandler) {
        activity.onBackInvokedDispatcher.registerOnBackInvokedCallback(priority, backInvokedCallback)
    }

    LaunchedEffect(handleBackHandler) {
        if (!handleBackHandler) {
            activity.onBackInvokedDispatcher.unregisterOnBackInvokedCallback(backInvokedCallback)
        }
    }

    DisposableEffect(activity.lifecycle, activity.onBackInvokedDispatcher) {
        onDispose {
            activity.onBackInvokedDispatcher.unregisterOnBackInvokedCallback(backInvokedCallback)
        }
    }
}

Как вы могли заметить, для компоновки требуется Android 13 или выше. Это просто, потому что OnBackInvokedCallback доступен только в Android 13 или выше. И я должен добавить, что обратный вызов заблокирует предстоящие обратные свайпы. Итак, если владелец жизненного цикла использует свой собственный OnBackInvokedCallback, то он не будет вызываться. Более того, если вы используете компонуемый BackHandler и BackInvokedHandler, ОС Android будет использовать компонуемый BackInvokedHandler и игнорировать компонуемый BackHandler. Или, другими словами, когда они оба включены, ОС Android предпочитает компонуемый BackInvokedHandler.

В общем, я надеюсь, что эта статья была полезной. Если у вас есть какие-либо вопросы или предложения, пожалуйста, дайте мне знать в комментариях. Я также создал репозиторий GitHub по этой теме с небольшим полем выбора приложения. Вы можете найти его ниже. Спасибо за чтение. Увидимся в следующей статье.

Не забудьте подписаться на меня для будущих блогов / статей.

ЛинкедИн

Всех вас люблю.

Будьте в курсе новых блогов.

Будьте осторожны.

Исходный код