2

Background

  • I have built a custom bottom sheet with three anchors.
  • There is a FAB for transitioning from BottomSheetState.Gone to BottomSheetState.Half.
  • This bottom sheet's content either doesn't cover, half covers, or fully covers a full screen GoogleMap Composable.
  • The maxHeight parameter is the full height in pixels of the parent Composable.
@ExperimentalMaterialApi
@Composable
fun AnchoredBottomSheet(
    state: BottomSheetState,
    maxHeight: Float,
    content: @Composable () -> Unit,
) {
    val swipeableState = rememberSwipeableState(initialValue = state)

    val anchors = mapOf(
        BottomSheetState.Gone.toAnchor(maxHeight),
        BottomSheetState.Half.toAnchor(maxHeight/2),
        BottomSheetState.Full.toAnchor(0),
    )

    Column(
        modifier = Modifier
            .height(maxHeight.toDp())
            .swipeable(
                enabled = swipeableState.currentValue != BottomSheetState.Gone,
                state = swipeableState,
                orientation = Orientation.Vertical,
                anchors = anchors,
            )
            .offset {
                IntOffset(
                    0,
                    swipeableState.offset.value.roundToInt()
                )
            }
    ) {
        content()
    }
}

Problem

  • When the app is in the BottomSheetState.Half state or the BottomSheetState.Gone,
  • and the user clicks on the GoogleMap portion of the screen,
  • clicks are caught by the AnchoredBottomSheet and do not pass through to the visible (GoogleMap) Composable.
  • For example in this photo the cyan portion of the screen represents the GoogleMap portion of the view in the BottomSheetState.Half state and it does not receive clicks. BottomSheetState.Half

Question

How can I make the my bottom sheet implementation only consume clicks/drags that occur on the content of the bottom sheet?

Lucas
  • 323
  • 1
  • 8

1 Answers1

2

The issue was in the ordering of the Modifier extension invocations. Modifier.swipeable() should happen after Modifier.offset().

@ExperimentalMaterialApi
@Composable
fun AnchoredBottomSheet(
    state: BottomSheetState,
    maxHeight: Float,
    content: @Composable () -> Unit,
) {
    val swipeableState = rememberSwipeableState(initialValue = state)

    val anchors = mapOf(
        BottomSheetState.Gone.toAnchor(maxHeight),
        BottomSheetState.Half.toAnchor(maxHeight/2),
        BottomSheetState.Full.toAnchor(0),
    )

    Column(
        modifier = Modifier
            .offset {
                IntOffset(
                    x = 0,
                    y = swipeableState.offset.value.roundToInt(),
                )
            }
            .swipeable(
                enabled = swipeableState.currentValue != BottomSheetState.Gone,
                state = swipeableState,
                orientation = Orientation.Vertical,
                anchors = BottomSheetState.getAnchors(maxHeight),
            )
    ) {
        content()
    }
}
Lucas
  • 323
  • 1
  • 8