skydoves / flexiblebottomsheet Goto Github PK
View Code? Open in Web Editor NEW๐ฌ Advanced Compose Multiplatform bottom sheet for segmented sizing and non-modal type, similar to Google Maps.
License: Apache License 2.0
๐ฌ Advanced Compose Multiplatform bottom sheet for segmented sizing and non-modal type, similar to Google Maps.
License: Apache License 2.0
Is your feature request related to a problem?
We'd like have the bottom sheet not automatically expand to intermediate height.
Describe the solution you'd like:
Add a new, optional parameter e.g. skipShow = false
to the FlexibleBottomSheet constructor and use the parameter in the LaunchedEffect at the bottom of the file
if (!skipShow && sheetState.hasFullyExpandedState) {
LaunchedEffect(sheetState) {
sheetState.slightlyExpand()
}
}
Describe alternatives you've considered:
I've tried snapping to the desired target as a launched effect but it only works with a delay.
Please complete the following information:
Describe the Bug:
With only Horizontal sides' insets scrim doesn't contain status bar ๐ง
windowInsets = BottomSheetDefaults.windowInsets.only(WindowInsetsSides.Horizontal)
Expected Behavior:
A clear description of what you expected to happen.
Describe the Bug:
In the case of M3 ModalBottomSheet, Dim processing is possible in the Status Bar area when BottomSheet is on the screen by specifying windowInsets = WindowInsets(top = 0)
.
But FlexibleBottomSheet not working by by specifying windowInsets = WindowInsets(top = 0)
.
Add a clear description about the problem.
M3 ModalBottomSheet | FlexibleBottomSheet |
---|---|
full code is here.
https://github.com/Project-Unifest/unifest-android/blob/develop/core/ui/src/main/kotlin/com/unifest/android/core/ui/component/FestivalBottomSheet.kt
Expected Behavior:
I hope dim processing is applied to the Status Bar area.
I tried to find option to disable hide Bottom Sheet when I dismiss, but I didn't find the solution, can you explain?
Initial state not working or not able to be set.
Tracing the library code, calling rememberFlexibleBottomSheetState
calls a private function rememberFlexibleSheetState
which has a default parameter of initialValue: FlexibleSheetValue = FlexibleSheetValue.Hidden
. The public method does not take that parameter, however, the initial state should evaluate to hidden regardless.
In my most basic implementation, the sheet always starts off a not hidden, intermediately expanded.
val sheetState = rememberFlexibleBottomSheetState(
isModal = false
)
FlexibleBottomSheet(
windowInsets = WindowInsets(0, 0, 0, 0),
onDismissRequest = { },
sheetState = sheetState,
) {
CircularProgressIndicator()
}
}
It's not clear how to set the initial state, or if it's supported. Am I missing something obvious?
Wrapping the entire FlexibleBottomSheet
in an if statement
and check some state before showing works, but then it gets awkward to have a nice animation to hide it when that state changes, it would just abruptly disappear.
Expected Behaviour:
sheetState isModal is not updating when changed during onTargetChanges function
val scope = rememberCoroutineScope()
var isModal : Boolean by remember { mutableStateOf(true) }
val sheetState = rememberFlexibleBottomSheetState(
flexibleSheetSize = FlexibleSheetSize(
fullyExpanded = 1.0f,
intermediatelyExpanded = 0.5f,
slightlyExpanded = 0f
),
isModal = isModal,
skipSlightlyExpanded = false,
)
FlexibleBottomSheet(
onDismissRequest = {
scope.launch {
sheetState.hide()
}
},
sheetState = sheetState,
onTargetChanges = { sheetValue ->
isModal = sheetValue.ordinal != 0
println("$TAG Sheet SheetValue: $sheetValue || IsModal:: $isModal || sheetModal :: ${sheetState.isModal}")
},
) {
Text(text = "Bottom Sheeeet!!!")
}
While printing the logs i found below result
SheetValue: Hidden || IsModal:: false || sheetModal :: true
I want my bottom sheet to behave as Modal only when it is not hidden i.e., visible
If I set isModal as true, then I am not able to access the background content when the sheet is hidden/removed by the user.
Am i missing anything?
Is your feature request related to a problem?
When we pull down the bottom sheet and hold it, even though the bottom sheet exists, it is possible to click behind it and navigate to another page, and then reopen the bottom sheet again, even if it is a modal bottom sheet.
Describe the solution you'd like:
Describe alternatives you've considered:
Is your feature request related to a problem?
No, not really.
A clear and concise description of what the problem is.
The current implementation does not support expanding until the sheet wraps its content.
Describe the solution you'd like:
It would be great if there was a parameter or extra sheet state that could be specified so that the bottom sheet can expand until it wraps all of its content.
Describe alternatives you've considered:
Although I have not yet tried it myself, this could potentially be achieved using the onGloballyPosition modifier (?).
ํ์ฌ ์นด์นด์ค ํฐ ์ฑ์ ์ฃผ์ฐจ ๊ธฐ๋ฅ์์ ์ฒ๋ผ flexibleํ bottom sheet + No Hidden State์ธ BottomSheet ๊ตฌํ์ ํ ์ ์๊ฒ skipHiddenState์ ๋ํด์ ์ ์๋๋ฆฝ๋๋ค.
@Composable
fun rememberFlexibleBottomSheetState(
skipIntermediatelyExpanded: Boolean = false,
skipSlightlyExpanded: Boolean = true,
skipHiddenState: Boolean = false,
isModal: Boolean = false,
containSystemBars: Boolean = false,
allowNestedScroll: Boolean = true,
animateSpec: AnimationSpec<Float> = SwipeableV2Defaults.AnimationSpec,
flexibleSheetSize: FlexibleSheetSize = FlexibleSheetSize(),
confirmValueChange: (FlexibleSheetValue) -> Boolean = { true },
initialValue: FlexibleSheetValue = FlexibleSheetValue.IntermediatelyExpanded,
): FlexibleSheetState = rememberFlexibleSheetState(
skipIntermediatelyExpanded = skipIntermediatelyExpanded,
skipSlightlyExpanded = skipSlightlyExpanded,
isModal = isModal,
animateSpec = animateSpec,
confirmValueChange = confirmValueChange,
flexibleSheetSize = flexibleSheetSize,
containSystemBars = containSystemBars,
allowNestedScroll = allowNestedScroll,
initialValue = initialValue,
skipHiddenState = skipHiddenState,
)
private rememberFlexibleBottomSheetState()์ ๊ฒฝ์ฐ์๋ skipHiddenState์ ํด๋นํ๋ ํ๋ผ๋ฏธํฐ๊ฐ ์๋๋ฐ public rememberFlexibleBottomSheetState()์ ๊ฒฝ์ฐ์๋ skipHiddenState๊ฐ ํ๋ผ๋ฏธํฐ์ ์์ด ์ถ๊ฐ๋ฅผ ํ์์ต๋๋ค.
fun Modifier.flexibleBottomSheetSwipeable(
sheetState: FlexibleSheetState,
flexibleSheetSize: FlexibleSheetSize,
anchorChangeHandler: AnchorChangeHandler<FlexibleSheetValue>,
sheetFullHeight: Float,
sheetConstraintHeight: Float,
screenMaxHeight: Float,
isModal: Boolean,
onDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit = {},
onDragStopped: CoroutineScope.(velocity: Float) -> Unit,
): Modifier = draggable(
state = sheetState.swipeableState.swipeDraggableState,
orientation = Orientation.Vertical,
enabled = sheetState.isVisible,
startDragImmediately = sheetState.swipeableState.isAnimationRunning,
onDragStarted = onDragStarted,
onDragStopped = onDragStopped,
)
.swipeAnchors(
state = sheetState.swipeableState,
anchorChangeHandler = anchorChangeHandler,
possibleValues = if (sheetState.skipHiddenState) {
setOf(
FlexibleSheetValue.IntermediatelyExpanded,
FlexibleSheetValue.SlightlyExpanded,
FlexibleSheetValue.FullyExpanded,
)
} else {
setOf(
FlexibleSheetValue.Hidden,
FlexibleSheetValue.IntermediatelyExpanded,
FlexibleSheetValue.SlightlyExpanded,
FlexibleSheetValue.FullyExpanded,
)
},
) { value, sheetSize ->
.... ์๋ต
skipHiddenState์ ๊ฐ์๋ฐ๋ผ possibleValues๋ฅผ ๋ค๋ฅด๊ฒํ์ฌ ๋ณด์์ต๋๋ค.
Please complete the following information:
Describe the Bug:
I've added a text field to the content of the bottom flexible sheet.
When clicked, the keyboard is not displayed.
is it possible to show the keyboard below the text field in the bottom sheet ?
Is your feature request related to a problem?
The standard bottom sheet will be gone after device configuration changes, such as rotating from portrait to landscape mode.
Describe the solution you'd like:
The non-modal standard bottom sheet should remain its state before the configuration changes.
Bottom Sheet is slightly visible at the bottom when it's hidden. You can see the WHITE line at the end of the photo
FlexibleBottomSheet(
sheetState = sheetState,
windowInsets = WindowInsets.waterfall,
tonalElevation = 0.dp,
shape = RectangleShape,
onDismissRequest = {
//NOOP
},
containerColor = White,
)
FlexibleSheetState(
flexibleSheetSize = FlexibleSheetSize(fullyExpanded = fullyExpandedRatio),
isModal = false,
skipSlightlyExpanded = true,
skipIntermediatelyExpanded = true,
containSystemBars = true,
allowNestedScroll = true,
animateSpec = SwipeableV2Defaults.AnimationSpec,
)
Please complete the following information:
Library Version
current latest version(0.1.2)
Affected Device(s) [e.g. Samsung Galaxy s10 with Android 9.0]
Galaxy zflip4 and also Pixel5(emulator)
When I expand the bottomSheet, there is a problem that can see the behind NavigationBar at the bottom.
code
package com.unifest.android.core.ui.component
import androidx.annotation.StringRes
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text2.input.TextFieldState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.VerticalDivider
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.skydoves.flexible.bottomsheet.material3.FlexibleBottomSheet
import com.skydoves.flexible.core.FlexibleSheetSize
import com.skydoves.flexible.core.rememberFlexibleBottomSheetState
import com.unifest.android.core.designsystem.ComponentPreview
import com.unifest.android.core.designsystem.R
import com.unifest.android.core.designsystem.component.FestivalSearchTextField
import com.unifest.android.core.designsystem.component.InterestedFestivalDeleteDialog
import com.unifest.android.core.designsystem.theme.Content3
import com.unifest.android.core.designsystem.theme.UnifestTheme
import com.unifest.android.core.domain.entity.Festival
import kotlinx.coroutines.launch
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class)
@Composable
fun FestivalSearchBottomSheet(
@StringRes searchTextHintRes: Int,
setFestivalSearchBottomSheetVisible: (Boolean) -> Unit,
interestedFestivals: MutableList<Festival>,
initSearchText: () -> Unit,
setEnableSearchMode: () -> Unit,
isSearchMode: Boolean,
setEnableEditMode: () -> Unit,
isInterestedFestivalDeleteDialogVisible: Boolean,
setInterestedFestivalDeleteDialogVisible: (Boolean) -> Unit,
isEditMode: Boolean = false,
) {
val selectedFestivals = remember { mutableStateListOf<Festival>() }
val bottomSheetState = rememberFlexibleBottomSheetState(
containSystemBars = true,
flexibleSheetSize = FlexibleSheetSize(),
isModal = true,
skipSlightlyExpanded = false,
)
FlexibleBottomSheet(
onDismissRequest = {
setFestivalSearchBottomSheetVisible(false)
},
sheetState = bottomSheetState,
containerColor = Color.White,
dragHandle = {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(top = 10.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
VerticalDivider(
modifier = Modifier
.width(80.dp)
.height(5.dp)
.clip(RoundedCornerShape(43.dp))
.background(Color(0xFFA0A0A0)),
)
}
},
) {
Box {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.White)
.padding(
bottom = WindowInsets.navigationBars
.asPaddingValues()
.calculateBottomPadding(),
),
) {
Spacer(modifier = Modifier.height(24.dp))
FestivalSearchTextField(
searchText = TextFieldState(),
searchTextHintRes = searchTextHintRes,
onSearch = {},
initSearchText = initSearchText,
setEnableSearchMode = setEnableSearchMode,
isSearchMode = isSearchMode,
modifier = Modifier
.height(46.dp)
.fillMaxWidth()
.padding(horizontal = 20.dp),
)
if (!isSearchMode) {
Spacer(modifier = Modifier.height(39.dp))
VerticalDivider(
modifier = Modifier
.fillMaxWidth()
.height(8.dp)
.background(Color(0xFFF1F3F7)),
)
Spacer(modifier = Modifier.height(21.dp))
InterestedFestivalsGrid(
selectedFestivals = interestedFestivals,
onFestivalSelected = { school ->
selectedFestivals.remove(school)
},
isEditMode = isEditMode,
setInterestedFestivalDeleteDialogVisible = setInterestedFestivalDeleteDialogVisible,
) {
TextButton(
onClick = setEnableEditMode,
) {
Text(
text = stringResource(id = R.string.edit),
color = Color.Black,
style = Content3,
)
}
}
}
}
if (isInterestedFestivalDeleteDialogVisible) {
InterestedFestivalDeleteDialog(
onCancelClick = {
setInterestedFestivalDeleteDialogVisible(false)
},
onConfirmClick = {
setInterestedFestivalDeleteDialogVisible(false)
},
)
}
}
}
}
@ComponentPreview
@Composable
fun SchoolSearchBottomSheetPreview() {
UnifestTheme {
FestivalSearchBottomSheet(
searchTextHintRes = R.string.festival_search_text_field_hint,
setFestivalSearchBottomSheetVisible = {},
interestedFestivals = mutableListOf(
Festival("https://picsum.photos/36", "์์ธ๋ํ๊ต", "์ค๋์ถ์ ", "05.06-05.08"),
Festival("https://picsum.photos/36", "์ฐ์ธ๋ํ๊ต", "์ฐ๋์ถ์ ", "05.06-05.08"),
Festival("https://picsum.photos/36", "๊ณ ๋ ค๋ํ๊ต", "๊ณ ๋์ถ์ ", "05.06-05.08"),
Festival("https://picsum.photos/36", "๊ฑด๊ตญ๋ํ๊ต", "๋
น์์ง๋", "05.06-05.08"),
Festival("https://picsum.photos/36", "์ฑ๊ท ๊ด๋ํ๊ต", "์ฑ๋์ถ์ ", "05.06-05.08"),
),
initSearchText = {},
setEnableSearchMode = {},
isSearchMode = false,
setEnableEditMode = {},
isInterestedFestivalDeleteDialogVisible = false,
isEditMode = false,
setInterestedFestivalDeleteDialogVisible = {},
)
}
}
The above problem also occurred even when the bottomPadding value related to WindowInsets was removed
Expected Behavior:
Even when the bottomSheet is extended, the Navigation Bar located behind the screen should not be visible.
Is your feature request related to a problem?
I am trying to use FlexibleBottomSheet
on a screen that uses Scaffold
and bottomBar
. When I add the FlexibleBottomSheet
to the screen it sits on top of the NavigationBar
.
Using the following state:
rememberFlexibleBottomSheetState(
isModal = false,
skipSlightlyExpanded = true,
flexibleSheetSize = FlexibleSheetSize().copy(
fullyExpanded = 0.5f,
intermediatelyExpanded = 0.05f,
)
)
Describe the solution you'd like:
I would like the sheet to be displayed below and above the NavigationBar
. Basically sitting on top of it with a tiny amount visible, then expanding when the user drags up.
Describe alternatives you've considered:
I've tried adding Modifier.padding()
but that causes the whole thing to vanish. I'm looking into setting the WindowInsets
next.
In my app I want the status bar from Android at the top of the screen (where time and battery status are shown) to not be visible.
Unfortunately, I didn't find a working solution to expand to the status bar area in the FullyExpanded sheet state.
Instead, on top of the bottom sheet there is some space (where normally the top bar is placed) and there is no way to close the space and make the bottom sheet to fully expand to the top of the screen.
I already tried:
I have made the bottom sheet to just fully expand for my needed case.
flexibleSheetSize = FlexibleSheetSize(
fullyExpanded = fullyExpandedRatio,
intermediatelyExpanded = 0f,
slightlyExpanded = 0f,
),
FlexibleSheetState(
flexibleSheetSize = flexibleSheetSize,
isModal = false,
skipSlightlyExpanded = true,
skipIntermediatelyExpanded = true,
containSystemBars = true,
allowNestedScroll = true,
animateSpec = SwipeableV2Defaults.AnimationSpec,
)
When I use a scrollable composable like a LazyColumn or a vertically scrollable Column, with allowNestedScroll = true
, I can drag/fling the bottom sheet down to try dismiss it but it doesn't hide it. I more exact words, let's say I'm dragging/flinging it down, when I release the finger the sheet goes right back up to fullyExpanded automatically. I don't have this problem when I don't use a scrollable component. I can't share any images/videos due to the project I'm working on.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.