Hello, `BackHandler` doesn't work inside `BottomSh...
# compose
g
Hello,
BackHandler
doesn't work inside
BottomSheetDialogFragment
, how can I intercept it on the dialog and forward it myself to Compose which is the UI within
BottomSheetDialog
?
So if anyone is looking for the answer to this issue, it seems like the dialog is the one catching the
onBackPressed
event and dismisses the dialog. To have Compose be connected to it, we have to do the following: In your fragment, catches the dialog when created:
Copy code
private lateinit var dialog: ComponentDialog

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    return BottomSheetDialog(requireContext(), theme).apply {
        fullyExpanded()
        notDraggable()
        withoutBackgroundDim()
    }.also { dialog = it }
}
Prepare the following extensions on `ComponentDialog`:
Copy code
private val ComponentDialog.asBackPressedDispatcherOwner: OnBackPressedDispatcherOwner
        get() = object : OnBackPressedDispatcherOwner {
            override val lifecycle: Lifecycle
                get() = this@asBackPressedDispatcherOwner.lifecycle
            override val onBackPressedDispatcher: OnBackPressedDispatcher
                get() = this@asBackPressedDispatcherOwner.onBackPressedDispatcher
        }
And then the only missing piece is in your ComposeView to wrap the content with `CompositionLocalProvider`:
Copy code
CompositionLocalProvider(
    LocalOnBackPressedDispatcherOwner provides dialog.asBackPressedDispatcherOwner
) {
    MainChatScreen(::dismiss)
}
Maybe @Ian Lake will tell me I missed something else, but in the meantime this seems to work 🤔
i
ComponentDialog already implements
OnBackPressedDispatcherOwner
as of Activity 1.5.0: https://developer.android.com/jetpack/androidx/releases/activity#1.5.0
And AppCompatDialog already extends from ComponentDialog as of AppCompat 1.5.0-alpha01: https://developer.android.com/jetpack/androidx/releases/appcompat#1.5.0-alpha01
And with this change, AppCompatDialog already sets the correct
ViewTreeOnBackPressedDispatcherOwner
on the returned dialog so that
LocalOnBackPressedDispatcherOwner
picks it up
And that change landed on March 16, so I'd expect it to be in the next AppCompat release (e.g., 1.7.0-alpha03)
In the mean time, I'd probably just set the ViewTreeOnBackPressedDispatcherOwner on your Dialog window's decorView
I assume you're already setting the ViewTreeLifecycleOwner and ViewTreeSavedStateRegistryOwner just to get your ComposeView to work in the BottomSheetDialog?
g
No I wasn't, and that's actually much better (no need to retain the dialog):
Copy code
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        return BottomSheetDialog(requireContext(), theme).apply {
            (...)
            initViewTreeOwners()
        }
    }
Here's it setting those itsefl:
Copy code
private fun ComponentDialog.initViewTreeOwners() {
    window?.decorView?.let {
        it.setViewTreeLifecycleOwner(this)
        it.setViewTreeOnBackPressedDispatcherOwner(this)
        it.setViewTreeSavedStateRegistryOwner(this)
    }
}
Thanks for the whole explanation and update on AppCompat release, I will be able to remove this at some point!
330 Views