Sepideh Vatankhah
Sepideh Vatankhah

Reputation: 745

How can we define a column with padding and just one item doesn't inherit the padding of the column in Jetpack Compose?

I have a column with many items, and I want to set the padding for the column because all items have the same padding except one of them which doesn't have padding, how can I consider an exception for that specific item? Or is it possible to add an attribute that says don't get your parent padding? I know I can remove padding for column and add one by one, but I want to ask anybody knows that, is there any other way?

Column(
        modifier = Modifier
            .fillMaxSize()
            .verticalScroll(rememberScrollState()),
            .padding(16.dp),
        verticalArrangement = Arrangement.spacedBy(16.dp)
    ) {
 Text(text = "Teaser1")

Text(text = "Teaser2")

Text(text = "Teaser3")

Text(text = "Teaser")

Text(text = "Teaser4")

Text(text = "Teaser5")

...

}

Thank you in advance for your help.

Upvotes: 5

Views: 1692

Answers (2)

Tom
Tom

Reputation: 360

Building on @PhilDukhov 's solution, I've made one minor change that might make this a little more general purpose. I was having problems with longer strings (see my example code below), or any other View that had a measured width greater than constraint.maxWidth. In that scenario, this line: placeable.place(x = -padding.roundToPx(), y = 0) would place the string partially off screen.

Here is my updated solution:

private fun Modifier.overrideParentHorizontalPadding(parentHorizontalPadding: Dp) =
    layout { measurable, constraints ->
        val padding = (parentHorizontalPadding).roundToPx()
        val noPaddingConstraints = constraints.copy(
            // Make the new maxWidth = maxWidth + twice the horizontal padding of the parent
            maxWidth = constraints.maxWidth + (padding * 2)
        )
        val placeable = measurable.measure(noPaddingConstraints)
        layout(placeable.width, placeable.height) {
            if (placeable.width > constraints.maxWidth) {
                placeable.place(x = 0, y = 0)
            } else {
                placeable.place(x = -padding, y = 0)
            }
        }
    }

@Preview(name = "Test Padding Override")
@Composable
private fun PaddingOverridePreview() {
    val padding = 20.dp

    Column(
        modifier = Modifier
            .background(Color.White)
            .padding(horizontal = 5.dp)
            .border(1.dp, Color.Gray)
            .padding(horizontal = padding)
            .border(1.dp, Color.Gray)
            .fillMaxWidth()
    ) {
        Text("Normal")
        Text(
            text = "Override this",
            modifier = Modifier
                .overrideParentHorizontalPadding(padding)
        )
        Text(
            maxLines = 1,
            text = "And this 0123456789 0123456789 0123456789 012",
            modifier = Modifier
                .overrideParentHorizontalPadding(padding)
        )
        Text("Normal")
    }
}

Upvotes: 2

Phil Dukhov
Phil Dukhov

Reputation: 87894

You can use Modifier.layout.

I override the width constraint by adding padding for measure, and applying the padding offset during place.

Text(
    text = "Teaser",
    modifier = Modifier
        .layout { measurable, constraints ->
            val noPaddingConstraints = constraints.copy(
                maxWidth = constraints.maxWidth + (padding * 2).roundToPx()
            ) 
            val placeable = measurable.measure(noPaddingConstraints)
            layout(placeable.width, placeable.height) {
                placeable.place(x = -padding.roundToPx(), y = 0)
            }
        }
)

Upvotes: 4

Related Questions