skip to Main Content

I want to achieve the following layout enter image description here

All the headers like Claim requested credentials, Claim received credentials, Pending requests etc are dynamic and will be coming from backend and the items for each header like Module 1:… etc are dynamic as well. Also I need the card to encapsulate both Header and the Body item.

Here is what I have tried

LazyColumn(
        modifier = Modifier
            .offset(x = 0.dp, y = 110.dp)
            .fillMaxSize()
            .background(
                shape = RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp),
                color = MaterialTheme.colors.primaryVariant
            )
            .padding(12.dp)
    ) {
        itemsIndexed(
            listOf(
                "Claim requested credentials",
                "Claim received credentials",
                "Pending Requests"
            )
        ) { index, item ->
            Card(
                modifier = Modifier
                    .fillMaxWidth()
                    .statusBarsPadding()
                    .background(
                        color = MaterialTheme.colors.primaryVariant,
                        shape = RoundedCornerShape(10.dp)
                    )
                ,elevation = 20.dp,
                contentColor = MaterialTheme.colors.primaryVariant,
                backgroundColor = MaterialTheme.colors.primaryVariant
            ) {
                Column(modifier = Modifier.padding(horizontal = 8.dp, vertical = 12.dp)) {
                    ManageCredentialHeader(text = item, vcsNo = 2)
                    LazyColumn(){
                        itemsIndexed(listOf(1,2,3)){ index, item ->
                            ManageCredentialItem()
                        }
                    }
                }
            }
        }
    }

But I get an error saying 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. 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 infinite constraints in the hierarchy above the scrolling container.

How to achieve this kind of dynamic layout with LazyColumn in compose. In react-native this was easily achieved using SectionList.

3

Answers


  1. I think problem there

                        LazyColumn(){
                            itemsIndexed(listOf(1,2,3)){ index, item ->
                                ManageCredentialItem()
                            }
                        }
    

    You cannot nest LasyColumn inside LazyColumn, but you can replace it like this:

    Column {
        for (index, item in listOf(1, 2, 3).withIndex()) {
            ManageCredentialItem()
        }
    }
    
    Login or Signup to reply.
  2. Looks like you need a single dynamic LazyColumn here.

    You don’t have to only use items at the topmost level – if you check out its source code, you’ll see that it’s just adds single item in a loop.

    You can build your lazy content by adding multiple items inside an other loop, something like this:

    LazyColumn {
        listOf(
            "Claim requested credentials",
            "Claim received credentials",
            "Pending Requests"
        ).forEach { header ->
            item(
                contentType = "header"
            ) {
                Text(header)
            }
            items(
                count = 10,
                contentType = "body",
            ) { bodyIndex ->
                Text(bodyIndex.toString())
            }
        }
    }
    
    Login or Signup to reply.
  3. In Jetpack Compose when you create layouts like LazyColumn or any other layout you measure your Composables as Measurables with the limits coming from Constraints as min/max width/height. Modifier.scroll or LazyList returns max as Constraints.Infinity which is not permitted for child LazyColumn. That’s why you get that exception.

    In this answer i explained which modifier returns which Constraints. You can check out Constraints section.

    Since you don’t have a height for the Column add a size modifier that changes maxHeight of inner LazyColumn from Constraints.Infinity to something finite such as

       Column(
                        modifier = Modifier
                            .padding(horizontal = 8.dp, vertical = 12.dp)
                            .heightIn(max = 500.dp) {
    
    
    }
    

    max height is not the fixed value set, it’s the biggest height that child LazyColumns can get. You can change it as required. Your items can grow in height up to this.

    Implementation

    @Composable
    private fun LazyListSample() {
        LazyColumn(
            modifier = Modifier
                .fillMaxSize()
                .background(
                    shape = RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp),
                    color = Color(0xffE3F2FD)
                )
                .padding(12.dp),
            contentPadding = PaddingValues(vertical = 10.dp),
            verticalArrangement = Arrangement.spacedBy(16.dp)
        ) {
    
            itemsIndexed(
                listOf(
                    "Claim requested credentials",
                    "Claim received credentials",
                    "Pending Requests"
                )
            ) { index, item ->
                Card(
                    modifier = Modifier
                        .fillMaxWidth()
                        .statusBarsPadding(),
                    elevation = 20.dp,
                    shape = RoundedCornerShape(10.dp),
    
                    ) {
                    Column(
                        modifier = Modifier
                            .padding(horizontal = 8.dp, vertical = 12.dp)
                            .heightIn(max = 500.dp)
                    ) {
                        ManageCredentialHeader(text = item, vcsNo = 2)
                        LazyColumn(
                            verticalArrangement = Arrangement.spacedBy(8.dp)
                        ) {
                            itemsIndexed(listOf(1, 2, 3)) { index, item ->
                                ManageCredentialItem()
                            }
                        }
                    }
                }
            }
        }
    }
    
    @Composable
    private fun ManageCredentialHeader(text: String, vcsNo: Int) {
        Row(modifier = Modifier.fillMaxWidth()) {
            Text(text)
            Spacer(modifier = Modifier.width(4.dp))
            Box( modifier = Modifier
                .size(24.dp)
                .background(Color.Blue,CircleShape)
                .padding(2.dp),
                contentAlignment = Alignment.Center
            ) {
                Text(
                    vcsNo.toString(),
                    color = Color.White
                )
            }
    
            Spacer(modifier = Modifier.weight(1f))
    
        }
    }
    
    @Composable
    private fun ManageCredentialItem() {
        Row(modifier = Modifier.padding(top = 16.dp)) {
            Column() {
                Text("Module 1 some text")
                CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
                    Text("Subtitle")
                }
            }
            Spacer(modifier = Modifier.weight(1f))
            Text(
                "VIEW",
                modifier = Modifier
                    .background(Color(0xff283593), RoundedCornerShape(8.dp))
                    .padding(6.dp),
                color = Color.White
            )
        }
    }
    

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search