Search code examples
androidandroid-jetpack-compose

How to override the system onbackpress() in Jetpack Compose


Problem:

In my compose page -> I have list of elements, if I press anyone, I will show sub contents in same page (hide the main content and show the sub content)

When I press the back button in the topbar, I handle the logic myself.

But I am unable to handle system back press.

Question:

Is there a way to override the onBackPressed() in Jetpack Compose?

My code:

@Composable
private fun AnimationRootView() {

    //Main content list
    Column() {

    }

    //Sub content list
    Column() {

        if (detail1Clicked)
            Detail1()
        if (detail2Clicked)
            Detail2()
    }
 ....
 ....
}

Solution

  • You can use BackHandler:

    @Composable
    fun TestScreen() {
        BackHandler {
            // your action
        }
    }
    

    To get the same effect as with super.onBackPressed() call, the most compose way it to use enabled parameter depending on your state:

    BackHandler(
        // your condition to enable handler
        enabled = isOverlayPresented
    ) {
        // your action to be called if back handler is enabled
        isOverlayPresented = false
    }
    

    If you need to both handle back press and perform default back action, you can use LocalOnBackPressedDispatcherOwner. Since BackHandler is also using it under the hood, you need to wait next recomposition to make sure your back handler is disabled, then you can perform onBackPressed:

    val onBackPressedDispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher
    var backPressHandled by remember { mutableStateOf(false) }
    val coroutineScope = rememberCoroutineScope()
    BackHandler(enabled = !backPressHandled) {
        println("back pressed")
        backPressHandled = true
        coroutineScope.launch {
            awaitFrame()
            onBackPressedDispatcher?.onBackPressed()
            backPressHandled = false
        }
    }