Reputation: 3402
In one of my composables, a Lazycolumn
is nested inside a Column
composable. I want to be able to scroll the entire Column
along with the Lazycolumn
. But, specifying the verticalScroll
modifier
property on Column
results in the following exception causing the app to crash. How can I fix this?
Exception
java.lang.IllegalStateException: Vertically scrollable component was measured with an infinity maximum height constraints, which is disallowed. One of the common reasons is nesting layouts like LazyColumn and Column(Modifier.verticalScroll()).
Composable
Column(
modifier = Modifier
.fillMaxWidth()
.verticalScroll(rememberScrollState())
.padding(bottom = 100.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
LazyColumn(
modifier = Modifier
.fillMaxWidth()
) {
items(
items = allItems!!,
key = { item ->
item.id
}
) { item ->
ShoppingListScreenItem(
navController = navController,
item = item,
sharedViewModel = sharedViewModel
) { isChecked ->
scope.launch {
shoppingListScreenViewModel.changeItemChecked(item!!, isChecked)
}
}
}
}
...
Button(
modifier = Modifier.padding(vertical = 24.dp),
onClick = {
navController.navigate(NavScreens.AddItemScreen.route) {
popUpTo(NavScreens.AddItemScreen.route) {
inclusive = true
}
}
}
) {
Text("Go to add item screen")
}
}
Upvotes: 5
Views: 6769
Reputation: 21
You should use nested scrolling
This is the google dev document: https://developer.android.com/develop/ui/compose/touch-input/pointer-input/scroll
verticalScroll only works with nested scrolling in different directions. just like:
Column(
modifier = Modifier
.verticalScroll(rememberScrollState())
) {
LazyRow(
modifier = Modifier
.fillMaxWidth()
) {
}
Row(
modifier = Modifier
.horizontalScroll(rememberScrollState())
) {
LazyColumn(
modifier = Modifier
.fillMaxHeight()
) {}
}
So if you want to use column nested lazyColumn you have to use NestedScroll.
val nested = object : NestedScrollConnection {
override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
return super.onPostFling(consumed, available)
}
override fun onPostScroll(
consumed: Offset,
available: Offset,
source: NestedScrollSource
): Offset {
return super.onPostScroll(consumed, available, source)
}
override suspend fun onPreFling(available: Velocity): Velocity {
return super.onPreFling(available)
}
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
return super.onPreScroll(available, source)
}
}
Column(
modifier = Modifier.nestedScroll(nested)
) {
SideEffect {
Log.i("refresh", "Column")
}
LazyColumn {
}
LazyColumn(
modifier = Modifier
) {
}
}
This is just an example. Please refer to the google dev documentation for specific requirements.
Upvotes: 2
Reputation: 66516
This happens when you wish to measure your LazyColumn
with Constraints
with Constraints.Infinity
for the maxHeight which is not permitted as described in error log. There should be a fixed height or you shouldn't have another Scrollable with same orientation.
Column(
modifier = Modifier
// This is the cause
.verticalScroll(rememberScrollState())
) {
LazyColumn(
// and not having a Modifier that could return non-infinite max height contraint
modifier = Modifier
.fillMaxWidth()
) {
}
If you don't know exact height you can assign Modifier.weight(1f)
to LazyColumn.
What i mean by measuring with with Constraints.Infinity is when you create a Layout
in Compose you use
Layout(modifier=modifier, content=content){
measurables: List<Measurable>, constraints: Constraints ->
}
You get child Composables as List<Measurable>
which you can measure with Constraints
provided by parent or the one you see fit by updating existing one with Constraints.copy
or fixed one when you build a custom Composable with Layout
.
val placeable = measurable.measure(constraints)
Constraints min/max
width/height
changes based on size modifier or scroll. When there is a scroll and you don't use any size modifier, Constraints
return
minHeight =0, maxHeight= Int.MAX_VALUE as Constraints.Infinity
Modifier.fillMaxWidth()
Modifier.fillMaxWidth().weight(1f)
Easiest way to check Constraints
with different Modifiers or with scroll is getting it from BoxWithConstraints
Upvotes: 6