Back press does not close bottom sheet in Android 33 and above

172 views Asked by At

I've encountered an issue with Jetpack Compose where the back press event doesn't close the bottom sheet on devices running Android 33 and above. Is there a way to override this behavior or implement a custom handling for the back press event in Jetpack Compose? I'm looking for insights or solutions to address this specific problem.

For more context, my project uses the navigation component for navigation. The bottom sheet works just fine in projects without it.

I tried to handle the back press using the Backhandler.

BackHandler {
    coroutineScope.launch {
        if (bottomSheetScaffoldState.isVisible) {
            showBottomSheet = false
            bottomSheetScaffoldState.hide()
        } else {
            showBottomSheet = true
            bottomSheetScaffoldState.show()
        }
    }
}

This is my bottom sheet

ModalBottomSheet(
    onDismissRequest = { showBottomSheet = false },
    shape = RoundedCornerShape(
        topEnd = Constants.BOTTOM_SHEET_CORNER_RADIUS,
        topStart = Constants.BOTTOM_SHEET_CORNER_RADIUS
    ),
    sheetState = bottomSheetScaffoldState,
    windowInsets = WindowInsets(0, 0, 0, 8),
) {
    BoxWithConstraints(
        Modifier
            .navigationBarsPadding()
            .padding(bottom = 10.dp)
    ) {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .padding(bottom = 10.dp)
                .navigationBarsPadding()
        ) {
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .clickable {
                      
                    }
                    .height(44.dp),
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Text(
                    text = "Discard Changes",
                    style = MaterialTheme.typography.bodyLarge,
                    fontWeight = FontWeight.Normal,
                    fontSize = 15.sp,
                    color = colorResource(
                        id = R.color.system_red
                    ),
                    textAlign = TextAlign.Start,
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(horizontal = 16.dp)
                )
            }
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .clickable {
                        coroutineScope
                            .launch {
                                bottomSheetScaffoldState.hide()
                            }
                            .invokeOnCompletion {
                                if (!bottomSheetScaffoldState.isVisible) {
                                    showBottomSheet = false
                                    keyboard?.show()
                                }
                            }
                    }
                    .height(44.dp),
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Text(
                    text = "Keep Editing",
                    style = MaterialTheme.typography.bodyLarge,
                    fontWeight = FontWeight.Normal,
                    fontSize = 15.sp,
                    color = if (!isSystemInDarkTheme()) colorResource(id = R.color.black) else colorResource(
                        id = R.color.white
                    ),
                    textAlign = TextAlign.Start,
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(horizontal = 16.dp)
                )
            }
        }
    }
}

This solution works fine for devices with Android 12 and below but does not work fine on devices with API 33 and above.

1

There are 1 answers

0
ISHAN KALANSOORIYA On

onBackPressed is deprecated for API 33 and above use getOnBackInvokedDispatcher instead. https://developer.android.com/guide/navigation/custom-back/predictive-back-gesture#kotlin

 if (BuildCompat.isAtLeastT()) {
    onBackInvokedDispatcher.registerOnBackInvokedCallback(
        OnBackInvokedDispatcher.PRIORITY_DEFAULT
    ) {
        /**
         * onBackPressed logic goes here. For instance:
         * Prevents closing the app to go home screen when in the
         * middle of entering data to a form
         * or from accidentally leaving a fragment with a WebView in it
         *
         * Unregistering the callback to stop intercepting the back gesture:
         * When the user transitions to the topmost screen (activity, fragment)
         * in the BackStack, unregister the callback by using
         * OnBackInvokeDispatcher.unregisterOnBackInvokedCallback
         * (https://developer.android.com/reference/kotlin/android/window/OnBackInvokedDispatcher#unregisteronbackinvokedcallback)
         */
    }
}