Search code examples
androidandroid-jetpack-compose

How to maintain composable's weight with respect to its intrinsic height in a scrollable Column?


I have this layout in which the first Box in the Column has the height set to 360.dp but also weight set to 1f so that it fills the available space:

@Composable
fun Test() {
    Scaffold { paddingValues ->
        Box(
            modifier = Modifier
                .fillMaxSize()
                .padding(paddingValues = paddingValues)
        ) {
            Column(
                modifier = Modifier
                    .matchParentSize()
                    .verticalScroll(rememberScrollState())
            ) {
                Box(
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(360.dp)
                        .weight(1f)
                        .background(brush = Brush.verticalGradient(listOf(Color.Blue, Color.Green)))
                )

                Box(
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(360.dp)
                        .background(brush = Brush.verticalGradient(listOf(Color.Blue, Color.Green)))
                )
            }
        }
    }
}

It looks like this:

Now, when the layout is rendered on smaller screen, the weighted Box is shrinking which is NOT what I want:

What I wanted instead was the first Box retaining its intrinsic height (360.dp) in this scenario so that the second Box would be reachable by scroll, just like this:

NOTE: I do not want to use any Spacer between those two Boxes to fill the remaining space - I really need to have the first Box always fill at least 360.dp and more if space is availble.

How can I achieve this?


Solution

  • You can get Column height by wrapping it with BoxWithConstraints, when it fills parent maxWidth/Height Constraints are equal to parent size, and after getting height you can set a conditional Modifier with then to set weight if total height of parent is bigger than 720.dp as

    @Preview
    @Composable
    fun Test() {
        Scaffold { paddingValues ->
            BoxWithConstraints(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(paddingValues = paddingValues)
            ) {
    
                val height = maxHeight
    
                Column(
                    modifier = Modifier
                        .matchParentSize()
                        .verticalScroll(rememberScrollState())
                ) {
                    Box(
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(360.dp)
                            .then(
                                if (height > 720.dp) Modifier.weight(1f) else Modifier
                            )
                            .background(brush = Brush.verticalGradient(listOf(Color.Blue, Color.Green)))
                    )
    
                    Box(
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(360.dp)
                            .background(brush = Brush.verticalGradient(listOf(Color.Blue, Color.Green)))
                    )
                }
            }
        }
    }
    

    enter image description here