Home > Software engineering >  Align composable to bottom of another composable in Jetpack compose?
Align composable to bottom of another composable in Jetpack compose?

Time:03-07

I have 3 composable in Column and I want to align 2nd composable to bottom of 1st composable like this:

But currently i'm getting output like this:

Here is my current code:

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposePlaygroundTheme {
                Column(modifier = Modifier
                    .fillMaxSize()) {
                    topControls("Game 1",34,Modifier.weight(1f))
                    centerControls()
                    bottomControls()
                }
            }
        }
    }
}

@Composable
fun topControls(gamename: String, totalTime: Int, modifier: Modifier) {
    Column(modifier = modifier
        .background(Color.LightGray)
        .padding(start = 24.dp, end = 24.dp, top = 24.dp)) {
        Row(modifier = Modifier.padding(end = 32.dp)) {
            Image(
                painter = painterResource(R.drawable.ic_launcher_foreground),
                contentDescription = "",
                Modifier
                    .height(32.dp)
                    .width(32.dp)
            )
            Text(
                text = gamename,
                modifier = Modifier
                    .weight(1f)
                    .align(Alignment.CenterVertically),
                textAlign = TextAlign.Center
            )
        }
        Text(text = totalTime.toString(),modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center,fontSize = 53.sp)
        Image(
            painter = painterResource(R.drawable.ic_launcher_background),
            contentDescription = "",
            Modifier.fillMaxSize(),
            contentScale = ContentScale.FillBounds
        )
    }
}

@Composable
fun centerControls() {
    Box(modifier = Modifier
        .fillMaxWidth()) {
        Divider(color = Color.Blue, thickness = 1.dp, modifier = Modifier.align(Alignment.Center))
        Row(modifier = Modifier.padding(start = 20.dp, end = 20.dp)) {
            Button(onClick = {  },colors = ButtonDefaults.buttonColors(backgroundColor = Color.Black,contentColor = Color.White), modifier = Modifier
                .weight(1f)
                .padding(end = 20.dp)
                .fillMaxWidth()) {
                Text(text = "End Game",modifier = Modifier
                    .wrapContentWidth()
                    .wrapContentHeight(), textAlign = TextAlign.Center,fontSize = 20.sp)
            }
            Image(painter = ColorPainter(Color.Gray), contentDescription = "", modifier = Modifier
                .padding(horizontal = 25.dp)
                .align(Alignment.CenterVertically)
                .height(32.dp)
                .width(32.dp))
        }

    }
}

@Composable
fun bottomControls() {
    Spacer(modifier = Modifier.height(170.dp))
}

Is there anyway I can achieve this in jetpack compose without using Constraint layout?

CodePudding user response:

Something like this should work

  ComposePlaygroundTheme {
                Column(modifier = Modifier
                    .fillMaxSize()) {
                    topControls("Game 1",34)
                    Box(modifier = Modifier.weight(1f)) { // FrameLayout, weight will occupy rest of the content
                          centerControls()
                          bottomControls() // will be stacked up on top of topControls()
                     }
                    
                }
            }

CodePudding user response:

As you need to place one view under an other one, you should use Box.

Using Modifier.align, you can specify position of your centerControls, in this case Alignment.BottomCenter.

Using Modifier.layout you can add offset, equal to half view size.

Column(modifier = Modifier
    .fillMaxSize()
) {
    Box(Modifier.weight(1f)) {
        topControls("Game 1", 34, Modifier.fillMaxHeight())
        centerControls(
            Modifier
                .align(Alignment.BottomCenter)
                .layout { measurable, constraints ->
                    val placeable = measurable.measure(constraints)
                    layout(placeable.width, placeable.height) {
                        placeable.place(0, placeable.height / 2)
                    }
                }
        )
    }
    bottomControls()
}

Result:

  • Related