I am using BottomSheetScaffold in one of my projects and I just put some content in the bottom sheet but when I swipe up on the expanded sheet, the sheet jumps/bounces, revealing the content of background.
Is there a way to remove this effect In BottomSheetScaffold? When it is expanded, swipe should not bounce the bottom sheet
A visual representation is attached below:
Code in question (please ignore custom theme values) :
val scaffoldState = rememberBottomSheetScaffoldState()
var currentSheetStat by remember { mutableStateOf(SheetContent.BookingRide) }
var sheetPeekHeight by remember {
mutableStateOf(420.dp)
}
BottomSheetScaffold(
scaffoldState = scaffoldState,
modifier = Modifier.fillMaxSize(),
sheetPeekHeight = sheetPeekHeight,
sheetShadowElevation = 0.dp,
sheetTonalElevation = 0.dp,
containerColor = Color.Transparent,
sheetContent = {
Column {
Column(
Modifier
.padding(
start = BnTheme.gaps.component,
end = BnTheme.gaps.component,
bottom = BnTheme.gaps.component
)
.fillMaxWidth())
{
Row(verticalAlignment = Alignment.CenterVertically) {
if(currentSheetStat == SheetContent.RideStarted) {
BnPebbleMedium(pebbleText = stringResource(id = commonR.string.sos),
hasLeadingIcon = true, leadingIcon = painterResource(id = commonR.drawable.ic_alert_badge),
leadingIconTint = BnTheme.colors.error, pebbleTextColor = BnTheme.colors.error,
pebbleContainer = BnTheme.colors.surfaceContainer)
}
Spacer(modifier = Modifier.weight(1f))
Card(
shape = RoundedCornerShape(100),
colors = CardDefaults.cardColors(
containerColor = BnTheme.colors.surfaceContainer
),
modifier = Modifier
.size(48.dp)
) {
Column(horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxSize()) {
Icon(
painter = painterResource(id = commonR.drawable.ic_locate),
contentDescription = null, Modifier.size(24.dp),
tint = shades_dark_blue_0
)
}
}
}
}
Card(
Modifier
.fillMaxWidth()
.background(Color.Transparent),
shape = RoundedCornerShape(topStart = BnTheme.cornerRadius.crL, topEnd = BnTheme.cornerRadius.crL),
colors = CardDefaults.cardColors(
containerColor = BnTheme.colors.surfaceContainer
),
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
) {
AnimatedContent(
targetState = currentSheetStat,
label = "",
) {
Crossfade(targetState = it, label = "bottom sheet animation") {
when(it) {
SheetContent.BookingRide -> {
//not important
}
SheetContent.ConfirmPickupLocation -> {
//not important
}
SheetContent.SendingRequest -> {
sheetPeekHeight = 220.dp
SheetContentSendingRequest{
currentSheetStat = SheetContent.NavigatorArrival
}
}
SheetContent.NavigatorArrival -> {
// not important
}
SheetContent.RideStarted -> {
//not important
}
}
}
}
}
}
},
sheetContainerColor = Color.Transparent,
sheetDragHandle = {
HorizontalDivider(thickness = 0.dp,
color = Color.Transparent)
}
) {
Box(modifier = Modifier.fillMaxSize()) {
ScreenContent() // the background map implementation
}
}
And this is the Sheet content
@Composable
fun SheetContentSendingRequest( onRideRequestSent : () -> Unit ) {
Column(modifier = Modifier
.fillMaxWidth()
.padding(
horizontal = BnTheme.gaps.component,
vertical = BnTheme.gaps.element
))
{
SheetDragHandle()
Spacer(modifier = Modifier.height(BnTheme.gaps.component))
Column (
Modifier
.padding(vertical = BnTheme.gaps.element)
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally){
BnText(
text = stringResource(id = commonR.string.sent_ride_request),
style = BnTheme.typography.titleSmallSemiBold,
color = BnTheme.colors.bodyPrimary
)
Row {
Row {
BnText(
text = stringResource(commonR.string.you_will_reach_destination_by),
style = BnTheme.typography.bodyMediumMedium,
color = BnTheme.colors.bodySecondary
)
Spacer(modifier = Modifier.height(BnTheme.gaps.mini))
BnText(
text = "11:11 AM",
style = BnTheme.typography.bodyMediumMedium,
color = BnTheme.colors.link
)
}
}
}
Spacer(modifier = Modifier.height(BnTheme.gaps.component))
Row {
LinearProgressIndicator(
progress = 1f,
trackColor = BnTheme.colors.primaryButtonOff,
color = BnTheme.colors.primaryButtonOn,
modifier = Modifier
.weight(1f)
.padding(horizontal = 12.dp)
.clip(RoundedCornerShape(100))
)
LinearProgressIndicator(
progress = 0f,
trackColor = BnTheme.colors.primaryButtonOff,
color = BnTheme.colors.primaryButtonOn,
modifier = Modifier
.weight(1f)
.padding(horizontal = 12.dp)
.clip(RoundedCornerShape(100))
)
LinearProgressIndicator(
progress = 0f,
trackColor = BnTheme.colors.primaryButtonOff,
color = BnTheme.colors.primaryButtonOn,
modifier = Modifier
.weight(1f)
.padding(horizontal = 12.dp)
.clip(RoundedCornerShape(100))
)
LinearProgressIndicator(
progress = 0f,
trackColor = BnTheme.colors.primaryButtonOff,
color = BnTheme.colors.primaryButtonOn,
modifier = Modifier
.weight(1f)
.padding(horizontal = 12.dp)
.clip(RoundedCornerShape(100))
)
}
Spacer(modifier = Modifier.height(BnTheme.gaps.component))
Icon(painter = painterResource(id = commonR.drawable.vector_shared_ride), contentDescription = null,
tint = Color.Unspecified, modifier = Modifier
.height(124.dp)
.align(Alignment.CenterHorizontally)
.noRippleClickable { onRideRequestSent() })
Spacer(modifier = Modifier.height(BnTheme.gaps.component))
}
}
This is probably not intended behavior, so you can consider opening an issue on the Google Issue Tracker so that the Android Developer Team can take a look at this. I can however present you a workaround.
I found that the sheetPeekHeight
parameter of the BottomSheetScaffold
Composable plays an important role. My guess is that you have set it to 0.dp
. If you set the sheetPeekHeight
to 10.dp
, the BottomSheet will have a rectangular Composable with 10dp height at the bottom area behind the BottomSheet.
You can use this behavior to cover the Scaffold background when swiping up. Please update your Composable as follows:
val scaffoldState = rememberBottomSheetScaffoldState()
val bottomSheetState = scaffoldState.bottomSheetState // just for convenience
BottomSheetScaffold(
scaffoldState = scaffoldState,
sheetPeekHeight =
if (bottomSheetState.currentValue == SheetValue.Expanded &&
bottomSheetState.targetValue == SheetValue.Expanded) {
50.dp
} else {
0.dp
},
sheetContent = {
//...
}
) {
//...
}
With this code, when the BottomSheet is expanded, we temporarily set the sheetPeekHeight
to 50dp to cover up the Scaffold background when swiping up.
Note however the limitation that when you positioned elements relatively in your Scaffold (for example by using a Column with verticalArrangement
), these elements will move, as the size of the Scaffold content is temporarily decreased when the BottomSheet is expanded.
In your case, sheetContainerColor = Color.Transparent
causes the problematic behavior. The only workaround that comes to my mind is to manually display a background overlay behind the BottomSheet. You can try it as follows:
Box(modifier = Modifier.fillMaxSize()) {
ScreenContent() // the background map implementation
Row(
modifier = Modifier
.align(Alignment.BottomCenter)
.fillMaxWidth()
.height(sheetPeekHeight - 25.dp)
.background(BnTheme.colors.surfaceContainer)
)
}
However, your code is a little bit strange. To expand or collapse a BottomSheet, you should use
scaffoldState.bottomSheetState.expand()
scaffoldState.bottomSheetState.partialExpand()
scaffoldState.bottomSheetState.hide()
instead of modifying the sheetPeekHeight
. Also have a look at the official documentation.