I'm trying to structure my composables this way:
Column ->
Tab(Child)
HorizontalPager (Child)->
LazyColumn (Child of Horizontal Pager)
I want to have a toolbar with (scroll | enterAlways) attribute, then a tablayout under, then a list below the tablayout.
I tried this structure but I'm getting this error
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()). If you want to add a
header before the list of items please add a header as a separate
item() before the main items() inside the LazyColumn scope.
This is the structure of what I currently have:
Box(
Modifier
.fillMaxSize()
.nestedScroll(nestedScrollConnection)
) {
Column(){
TabRow(
) {
}
HorizontalPager(
) {
LazyColumn {
}
}
}
TopAppBar()
}
Is there any alternative way to achieve a nested Lazycolumn inside a HorizontalPager and the HorizontalPager will have Column as it's parent?
I gave the below code a try in android studio and did not have any crashes.
Box(
Modifier
.fillMaxSize()
.nestedScroll(nestedScrollConnection)
) {
Column(){
TabRow() { }
HorizontalPager() {
LazyColumn (modifier = Modifier.Height(200.dp)) {
}
}
}
TopAppBar()
}
Related
I got this error message, And I don't get it.
java.lang.IllegalState
Exception: 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()). If you want to add a header before
the list of items please add a header as a separate item() before the
main items() inside the LazyColumn scope. There are could be other
reasons for this to happen: your ComposeView was added into a
LinearLayout with some weight, you applied
Modifier.wrapContentSize(unbounded = true) or wrote a custom layout.
Please try to remove the source of infinit
e constraints in the hierarchy above the scrolling container.
Here's example code.
#Composable
fun SupplementSearchScreen(
onSearch: (String) -> List<Vitamin>,
updateRecentAddedSupplementList: List<Vitamin>
) {
LazyColumn(
modifier = Modifier
.fillMaxSize()
) {
item{
SupplementSearchResultCard(someList)
}
}
}
#Composable
fun SupplementSearchScreen(list:List<SomeList>){
ContentCard(
modifier = Modifier.fillMaxWidth()
) {
Text(
text = "Hello World",
fontSize = 16.sp,
color = Color.Black
)
LazyColumn(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
) {
items(list){ resultItem ->
SearchResultItem(resultItem)
}
}
}
}
What's wrong here?
Lazy column needs fixed height component as parent to achieve lazy behavior,
if add lazy column inside parent with modifier Modifier.verticalScroll() or another Lazy column it will get infinite height it wont be able to decide when to compose and when to dispose an composable, instead use items{} of block of lazy column
in xml also same issue appears if wrap recyclerview inside nested scroll view but in xml instead of showing error it cause ANR as items increases in Recycler view adapter
You can use:
Modifier.height(LocalConfiguration.current.screenHeightDp.dp)
on the first lazy column to get all screen height.
I don't know if something like this will work for you but just to try it out.
You can't directly use LazyColumn inside LazyColumn. Just use LazyColumn with different types like this:
sealed interface Item {
data class SearchCard(val name: String) : Item
data class SearchText(val name: String): Item
}
#Composable
fun SearchScreen(list: List<Item>) {
LazyColumn {
items(list.size) { index ->
when (list[index]) {
is Item.SearchCard -> TODO()
is Item.SearchText -> TODO()
}
}
}
}
I have many Composables and I want to collapse Composable code inside like in xml. Is there extension for that?
Your post title is a bit misleading, but I think your'e asking how to collapse/expand "code" not the actual widget/ui.
I'm not sure if this is exactly what you want, but you can expand/collapse a specific area of your code if you wrap them within region/endregion without the need of any plugin or configuration, its almost the same behavior that your'e expecting from the xml editor, and you can do this anywhere not only to a function.
expanded code region
collapsed code region
Sample Inner composable expanded
Sample Inner composable collapsed
If you wish to make your Column collapse or expand without animation you simply need to add a if statement and set true to display false to collapse
var visible by remember {
mutableStateOf(true)
}
Column(modifier = Modifier.fillMaxSize()) {
Text("Click to expand or collapse", modifier = Modifier
.fillMaxWidth()
.clickable {
visible = !visible
}
)
if(visible) {
// Content to be collapsed or displayed
}
}
If you wish to collapse or expand with animation you can check out AnimatedVisbility composable
var visible by remember {
mutableStateOf(true)
}
Column(modifier = Modifier.fillMaxSize()) {
Text("Click to expand or collapse", modifier = Modifier
.fillMaxWidth()
.clickable {
visible = !visible
}
)
AnimatedVisibility(visible = visible) {
Column {
// Content to be collapsed or displayed
}
}
}
I have empty fragment with composable:
setContent {
Surface(
modifier = Modifier
.fillMaxWidth().fillMaxHeight().padding(bottom = 48.dp, top = 16.dp),
color = colorResource(id = R.color.usaa_white)
) {
val itemsList = (0..50).toList()
val itemsIndexedList = listOf("A", "B", "C")
LazyColumn(
) {
items(itemsList.size) {
Text("Item is $it")
}
item {
Text("Single item")
}
itemsIndexed(itemsIndexedList) { index, item ->
Text("Item at index $index is $item")
}
}
}
}
the problem is: I can only scroll the content until "Single Item" row and the rest of content is hidden. I added some padding to make sure that it wasn't bottomNavBar covering the list but it's still cropped.
Looks like the issue is caused by bottomNavBar. What's interesting is that it happens only with LazyColumn and works fine when I use Column
The fix I found is to add contentPadding to the bottom. (But hope to find better solution)
LazyColumn(contentPadding = PaddingValues(bottom = 70.dp)) { }
Use Scaffold (check documentation).
Scaffold has a generic content trailing lambda slot. The lambda receives an instance of PaddingValues that should be applied to the content root — for example, via Modifier.padding — to offset the top and bottom bars, if they exist.
setContent {
Scaffold { contentPadding ->
Box(
modifier = Modifier.padding(contentPadding)
) {
// Your code
}
}
}
Hope it helps !
With RecyclerView, I can make some ViewHolder not recyclable (follow some answers in
I want my RecyclerView to not recycle some items).
Can I make LazyColumn to not recompose some items (similar to make RecyclerView don't recycle some ViewHolder)? I have few items in LazyColumn with some big images, it recompose after scrolling down and up so scroll is not smooth.
I met the same problem and use Column instead with a modifier vertical scroll. If you don't want it recycle view, just load all ( few items)
Column(
modifier = Modifier
.constrainAs(listView) {
top.linkTo(
parent.top
)
}
.fillMaxSize()
.verticalScroll(rememberScrollState())
) {
list.forEachIndexed { index, itemModel ->
ItemView(itemModel, index) {
// on item click
}
}
Spacer(modifier = Modifier.height(40.dp))
}
I had a similar issue with a composable that is heavily manipulating bitmaps and then draw them on a canvas. You noticed that processing while scrolling the lazyColumn up and down.
To face this issue a stored my manipulated bitmaps in a List<ImageBitmap> as rememberSaveable
val rememberFruits by rememberSaveable(images) {
mutableStateOf(doBitmapOperations(images))
}
Canvas(
modifier = Modifier
.fillMaxWidth()
.height(height)
.constrainAs(circle) {}
) {
rememberFruits
.forEach { createScaledImageBitmap ->
val (image, offset) = createScaledImageBitmap
drawImage(
image = image,
topLeft = offset
)
}
}
My item in the lazyColumn was still recomposed but the heavy bitmap operations were no more executed while scrolling and making scrolling up and down smooth.
hope it helps!
I want to change LayoutManger(I don't know what that is called in jetpack compose) for LazyColumn so I can make the items scroll horizontally or vertically or in grid.
With 1.0.0 you can use:
LazyColumn : produces a vertically scrolling list
LazyRow: produces a horizontally scrolling list
Something like:
LazyColumn {
items((1..1000).toList()) {
Text(text = "Item $it")
}
}
the LazyVerticalGrid provides experimental support for displaying items in a grid.
Something like:
val numbers = (0..20).toList()
LazyVerticalGrid(
cells = GridCells.Fixed(4)
) {
items(numbers) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(text = "Number")
Text(text = " $it",)
}
}
}
In Jetpack Compose you can use LazyRow for horizontal scroll. LazyVerticalGrid can be used for Grid, which is still an experimental API. Read more here.
This for complete details about lists.
Official Jetpack Compose samples