Ezzy Wachira
Ezzy Wachira

Reputation: 390

How do I stack components on top of each other in jetpack compose?

I want to create a dashboard and I want this kind of layout on top. How do I achieve a layout like this one in jetpack compose? top dashboard layout, top dashboard layout 2

Upvotes: 7

Views: 15577

Answers (3)

Rizwan
Rizwan

Reputation: 1662

If you want to create a stack view with a list of content you can do that with the below code, here Arrangement.spacedBy((-50).dp) is used for giving the stack effect.

@Composable
fun CardsStackView(cards: List<CardUiModel> = getMockedCards()) {
    LazyColumn(
        verticalArrangement = Arrangement.spacedBy((-50).dp),
        modifier = Modifier
            .padding(top = 50.dp, end = 10.dp, start = 10.dp)
    ) {
        itemsIndexed(cards) { index, card ->
            CardView(index, card)
        }
    }
}


@Composable
fun CardView(index: Int, cardUiModel: CardUiModel) {
    Card(
        shape = RoundedCornerShape(8.dp),
        modifier = Modifier
            .height(80.dp)
            .width(260.dp)
    ) {
        Surface(
            modifier = Modifier.fillMaxSize(),
            color = getCardColor(index)
        ) {
            Box(contentAlignment = Center) {
                Text(text = cardUiModel.name)
            }
        }
    }
}

private fun getMockedCards() = listOf(
    CardUiModel("Visa"),
    CardUiModel("Amex"),
    CardUiModel("Rupay"),
    CardUiModel("Master Card")
)

private fun getCardColor(index: Int) =
    when (index) {
        0 -> Color.Blue
        1 -> Color.Magenta
        2 -> Color.Cyan
        3 -> Color.Red
        else -> Color.Yellow
    }

data class CardUiModel(val name: String)


@Preview(showBackground = true, device = Devices.PIXEL_XL)
@Composable
fun CardsStackViewPreview() {
    MaterialTheme {
        CardsStackView()
    }
}

It will look like the below Image

enter image description here

Upvotes: 4

Thracian
Thracian

Reputation: 67248

You can use a Box or BoxWithConstraints to achieve that look. The key thing here is to align the one in center to bottom and add bottom padding as big as the sum of height of Composable at the bottom and the half height of at the bottom since your Composables at the bottom and at the top don't have equal heights.

@Composable
private fun MyComposable(modifier: Modifier = Modifier) {
    BoxWithConstraints(modifier = modifier.fillMaxWidth(1f)) {
        val maxHeight = this.maxHeight

        val topHeight: Dp = maxHeight * 2 / 3
        val bottomHeight: Dp = maxHeight / 3

        val centerHeight = 100.dp

        val centerPaddingBottom = bottomHeight - centerHeight / 2

        Top(
            modifier = Modifier
                .fillMaxWidth()
                .align(Alignment.TopCenter)
                .height(topHeight)
        )

        Bottom(
            modifier = Modifier
                .fillMaxWidth()
                .align(Alignment.BottomCenter)
                .height(bottomHeight)
        )

        Center(
            modifier = Modifier
                .padding(start = 10.dp, end = 10.dp, bottom = centerPaddingBottom)
                .fillMaxWidth()
                .height(centerHeight)
                .align(Alignment.BottomCenter)
        )
    }
}

@Composable
private fun Top(modifier: Modifier) {
    Column(modifier.background(Blue400)) {

    }
}

@Composable
private fun Bottom(modifier: Modifier) {
    Column(modifier.background(Color.White)) {

    }
}

@Composable
fun Center(modifier: Modifier) {
    Column(modifier.background(Color.Red, shape = RoundedCornerShape(10.dp))) {

    }
}

Result

Upvotes: 8

Yuri Schimke
Yuri Schimke

Reputation: 13488

Generally you can use a Box.

See the example here https://foso.github.io/Jetpack-Compose-Playground/layout/box/

    Box(Modifier.fillMaxSize()) {
        Text("This text is drawn first", modifier = Modifier.align(Alignment.TopCenter))
        Box(
            Modifier.align(Alignment.TopCenter).fillMaxHeight().width(
                50.dp
            ).background( Color.Blue)
        )
        Text("This text is drawn last", modifier = Modifier.align(Alignment.Center))
        FloatingActionButton(
            modifier = Modifier.align(Alignment.BottomEnd).padding(12.dp),
            onClick = {}
        ) {
            Text("+")
        }
    }

Upvotes: 0

Related Questions