Search code examples
androidkotlinandroid-jetpackandroid-jetpack-compose

An alternative solution to set negative padding values in Jetpack Compose? (java.lang.IllegalArgumentException: Padding must be non-negative)


I'm trying to assign a negative value to the padding modifier but the app had crashed. Have a look at my code. Thanks if you can help or give me an alternative solution

In my example, I assign Modifier.padding(horizontal = 16.dp)to parent compose (LazyColum). But I want the first child (Image) to be Modifier.padding(horizontal = -16.dp) to fill the full width of the screen. Instead, I had to assign each padding value to each child.

Crash log: java.lang.IllegalArgumentException: Padding must be non-negative

enter image description here

Code snippet

LazyColumn(modifier = Modifier.padding(16.dp), state = lazyListState) {
    item {
        Image(
            modifier = Modifier
                .fillMaxWidth()
                .padding(-16.dp) // Crashed here!
                .height(200.dp),
            painter = painterResource(id = puppy.artwork),
            contentDescription = "Puppy ArtWork",
            contentScale = ContentScale.Crop
        )
    }
    item {
        Row(
            modifier = Modifier
                .padding(horizontal = 16.dp)
                .padding(top = 16.dp)
        ) {
            Text(text = puppy.name, style = MaterialTheme.typography.h4)
            Spacer(modifier = Modifier.weight(1f))
            Price(puppy.pricePerHour)
        }
    }
    item {
        CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
            Text(
                modifier = Modifier.padding(top = 16.dp)
                text = puppy.about
            )
        }
    }
    item {
        PuppyInfo(
            modifier = Modifier
                .fillMaxWidth()
                .padding(top = 16.dp),
            puppy = puppy
        )
    }
    .... // A lot of children here
    
}

Solution

  • If you want to increase not only the positioning but also the width in both horizontal directions, you can use the layout() modifier. I wrote a modifier extension function which can be used to ignore the parent padding:

    fun Modifier.ignoreHorizontalParentPadding(horizontal: Dp): Modifier {
        return this.layout { measurable, constraints ->
            val overridenWidth = constraints.maxWidth + 2 * horizontal.roundToPx()
            val placeable = measurable.measure(constraints.copy(maxWidth = overridenWidth))
            layout(placeable.width, placeable.height) {
                placeable.place(0, 0)
            }
        }
    }