How to set half expand ratio to bottom sheet in Compose? - android

In XML we have material3 bottom sheet. It allows us to set behavior of bottom sheet. It can be updated like:
bottomSheetBehavior.halfExpandedRatio = 0.6
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HALF_EXPANDED
I'm migrating project to Compose. My app used this half expanded ratio for 3 positioned bottom sheet: collapsed, half expanded, expanded. Now i'm trying to create bottom sheet like that:
val sheetState = rememberBottomSheetState(
initialValue = BottomSheetValue.Collapsed
)
val scaffoldState = rememberBottomSheetScaffoldState(
bottomSheetState = sheetState
)
BottomSheetScaffold(
scaffoldState = scaffoldState,
sheetContent = {}
) {}
But it looks like we don't have those behavior attributes here. Can we get the same behavior as in XML with half expanded bottom sheet?

Yes, it's possible. But it's a little bit of work. You basically have to provide your own implementations of the classes BottomSheetScaffold and SwipeableState as well as any related enums, classes and Composable functions used by these two.
The main points to focus on:
provide a third value to BottomSheetValue for the half-expanded state
provide a function that animates the half-expansion (similar to functions expand() and collapse() in BottomSheetState) as well as a property that checks if the bottom sheet is half expanded (similar to val isExpanded: Boolean)
add a third swipeable anchor to BottomSheetScaffold with the half expansion value you want to achieve (check line fullHeight - peekHeightPx to Collapsed, here is where you want to add your custom anchor)
handle the half expanded state in the .semantics block of the Modifier in BottomSheetScaffold
You might need to tweak a few more things depending on your specific requirement. It can take a while to set up everything but once it's done, it works like a charm.

Related

LazyColumn cuts off items when using with BottomNavigationView and Toolbar

LazyColumn in Jetpack Compose works fine with Scaffold and its inner padding according to this link. but when I try to use it inside a Fragment, it's items cut off by Toolbar and BottomNavigationView.
should I calculate inner padding manually depending on Toolbar and BottomNavigationViewsize or is there a better solution?
here's the structure. items of lazyColumn are colorful.
as you can see blue item is cut off.
update:
I realized that this behavior is because root of activity is a CoordinatorLayout and my container has appbar_scrolling_view_behavior. I tried this, but it didn't work.
I'm not sure if this would help, but you can try adding the height of the Bottom Navigation view as a bottom content padding to the LazyColumn or to a transparent widget inside another item{…} scope.
as a content padding
LazyColumn(
modifier = Modifier
.fillMaxSize(),
contentPadding = PaddingValues(bottom = <Bottom navigation height>)
) {…}
or as another item scope
LazyColumn(
modifier = Modifier
.fillMaxSize()
) {
items (..) {…}
item {
Box(
modifier = Modifier.height(<Bottom navigation view height>)
)
}
}

Decrease horizontal scroll width for BasicTextField in compose

In Jetpack Compose I am using BasicTextField and I want to add my own horizontalScroll for it. When I apply it, it seems to have built in minimum width, so even if content fits, user is still able to scroll.
I don't have this issue if I remove horizontal scroll and use singleLine = true mode. Then BasicTextField becomes scrollable only when entered value doesn't fit.
Is there any way to add some sort of "wrap content" flag for horizontal scroll?
The implementation is pretty standart, I add horizontal scroll to it like this:
var scrollState by remember { mutableStateOf(ScrollState(0)) }
BasicTextField(
modifier = Modifier
.horizontalScroll(state = scrollState, reverseScrolling = true),
singleLine = true,
...

Bottom Sheet content is showing for a second before activity content in Jetpack compose

I have implemented bottom sheet in jetpack compose with BottomSheetScaffold in a screen and default state is initialValue = BottomSheetValue.Collapsed.
When screen appears on device then Bottom sheet content is displayed for a second and then activity scope layout are presented and then bottom sheet behaves like it should. I am trying to remove this glitch from bottom sheet. Please let me know the suggestions which I can implement to remove this glitch.
Bottom sheet is working fine but it appears for a second before screen content and then disappears. This glitch needs to be removed.
Use a state for initial value storage, try
rememberModalBottomSheetState(
initialValue = ModalBottomSheetValue.Hidden,
)
I use this way to show the bottom sheets
val bottomSheetState = rememberModalBottomSheetState(
initialValue = ModalBottomSheetValue.Hidden,
)
ModalBottomSheetLayout(
sheetState = bottomSheetState,
sheetContent = {
//Sheet content
},
scrimColor = <SCREEN OVERLAY COLOR>,
sheetBackgroundColor = <BACKGROUND COLOR>
) {//Your Screen Code}
Hope this work for you!

How to scroll Jetpack Compose screen that overflows its contents?

I have an Add Shopping List item Jetpack Compose screen which contains several TextField inputs and an image container at the bottom. The screen overflows at the bottom and is cut off. How can I scroll the screen?
Add Modifier.scrollable(..) to the container that you wish to make scrollable.
Code would be something like this:
val scrollState = rememberScrollState()
...
Box( // or whatever your parent composable is
modifier = Modifier
.scrollable(state = scrollState, orientation = Orientation.Vertical)
) {
...
}
Of course, there are other Modifier methods for making composables scrollable that might fit better for your case.

Jetpack Compose animation is laggy if runs inside xml ComposeView with wrap_content height

I have kind of persistent BottomSheet styled Composable added to Fragment's xml (of course, using ComposeView). I need it to take only the required height, so it's only attached to start, end and bottom of parent ConstraintLayout, like so:
<androidx.compose.ui.platform.ComposeView
android:id="#+id/dashboard"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
ComposeView's root is a Column that contains some type of expandable composable and buttons underneath it. I need ComposeView to shrink or grow when expandable content is collapsed/revealed respectively. I have expandable's content wrapped in AnimatedContent:
#Composable
fun DashboardExpandableContent(modifier: Modifier = Modifier, expanded: Boolean) {
AnimatedContent(
modifier = modifier,
targetState = expanded,
transitionSpec = {
fadeIn(animationSpec = tween(durationMillis = 250)) with
fadeOut(animationSpec = tween(durationMillis = 250)) using SizeTransform()
}
) { currentlyExpanded ->
if (currentlyExpanded) {
ExpandedContent()
} else {
CollapsedContent()
}
}
}
But everything shakes like crazy during animation when I set xml height to wrap_content. Looks like it's because Android tries to measure my ComposeView during animation.
A possible hack I found is to change height in xml to a static value (i.e, constraint it to parent top), and add a Spacer with weight 1.0f as the Column's first child. Then the animation works just fine.
But I need it to have a dynamic height because other views (like onboarding popups) in xml layout rely on that. How can I make it work?

Categories

Resources