Search code examples
androidandroid-jetpack-composeresponsiveness

How to create responsive layouts with Jetpack Compose?


In the traditional view system, I handled responsiveness by using bias/guidelines/weights/wrap_content/avoiding hard coding dimensions/placing views relative to each other in Constraint Layout, using 'sdp' and 'ssp' etc.

How do I create responsive layouts with Jetpack Compose? I've been searching for info regarding it but unable to find.

Please help!


Solution

  • Two things can help you build flexible and responsive layouts in compose.

    1 - Use the Weight modifier in Row and Column

    A composable size is defined by the content it’s wrapping by default. You can set a composable size to be flexible within its parent. Let’s take a Row that contains two two Box composables. The first box is given twice the weight of the second, so it's given twice the width. Since the Row is 210.dp wide, the first Box is 140.dp wide, and the second is 70.dp:

    @Composable
    fun FlexibleComposable() {
        Row(Modifier.width(210.dp)) {
            Box(Modifier.weight(2f).height(50.dp).background(Color.Blue))
            Box(Modifier.weight(1f).height(50.dp).background(Color.Red))
        }
    }
    

    This results in:

    enter image description here

    2 - Use BoxWithConstraints

    In order to know the constraints coming from the parent and design the layout accordingly, you can use a BoxWithConstraints. The measurement constraints can be found in the scope of the content lambda. You can use these measurement constraints to compose different layouts for different screen configurations.

    It lets you access properties such as the min/max height and width:

    @Composable
    fun WithConstraintsComposable() {
        BoxWithConstraints {
            Text("My minHeight is $minHeight while my maxWidth is $maxWidth")
        }
    }
    

    Example usage:

    BoxWithConstraints {
        val rectangleHeight = 100.dp
        if (maxHeight < rectangleHeight * 2) {
            Box(Modifier.size(50.dp, rectangleHeight).background(Color.Blue))
        } else {
            Column {
                Box(Modifier.size(50.dp, rectangleHeight).background(Color.Blue))
                Box(Modifier.size(50.dp, rectangleHeight).background(Color.Gray))
            }
        }
    }