androidandroid-jetpack-composeandroid-jetpack-compose-modifierandroid-modalbottomsheetlayout

Android Compose ModalBottomSheetLayout outside click


I want to catch event when user clicks outside of ModalBottomSheetLayout. I wrapped ModalBottomSheetLayout with Box which is full size of the screen and set click listener. But Click listener only works when I click on the ModalBottomSheetLayout but not outside. I guess ModalBottomSheetLayout already consumes tap events and doesn't allow me to catch it?

Box(
    modifier = Modifier
        .clickable {
            Log.e("TAG", "clicked!")
        }.pointerInput(Unit) {
            detectTapGestures {
                Log.e("TAG", "tapped!")
            }
        }
        .fillMaxSize()
) {
    ModalBottomSheetLayout(
        sheetState = sheetState,
        sheetContent = {
            content()
        }
    )
}

Is there a way to catch the event of click/tap outside of ModalBottomSheetLayout?


Solution

  • ModalBottomSheetLayout api doesn't allow you to catch this events, but you can do the following:

    Box(
        modifier = Modifier
            .pointerInteropFilter {
                val bottomSheetShown = sheetState.currentValue != ModalBottomSheetValue.Hidden
                val outside = it.y < sheetState.offset.value
    
                if (bottomSheetShown && outside) {
                    // do you own logic here
                    Log.d("BottomSheet", "MotionEvent outside")
                    true
                } else {
                    false
                }
            }
    ) {
        ModalBottomSheetLayout(
            sheetContent = { BottomSheetContent() },
            content = { Screen(onShow = { coroutineScope.launch { sheetState.show() } }) },
            sheetState = sheetState,
        )
    }
    

    This way you will get all the MotionEvents inside of the if (bottomSheetShown && outside block. There you can process this events, do you business and after that ether pass it forward to the bottom sheet (by returning false) or block it (by returning true - then your bottom sheet will not get this events)