Search code examples
androidandroid-jetpack-composepaddingedge-to-edge

PaddingValues except bottomPadding in Jetpack Compose


Issue

I'm looking for a way to alter PaddingValues, so that they don't include any BottomPadding. My current Implementation looks like this, but here i need to pass LayoutDirection, which feels really clumsy.

fun PaddingValues.exceptBottomPadding(layoutDirection: LayoutDirection) =
    PaddingValues(
        top = calculateTopPadding(),
        bottom = 0.dp,
        end = calculateEndPadding(layoutDirection),
        start = calculateStartPadding(layoutDirection)
    )

I initially had hoped there would be a data-class-like way of altering PaddingValues, e.g. myPadding.copy(bottom = 0.dp), but nope, this would have been to easy...


Usecase

I'm going "edge to edge" with my Material3-Android-App. For that my Scaffold provides my content with PaddingValues (inclusive Insets).

However, my main content scrolling view should also be edge to edge, so i'd like to ignore the bottom part of the PaddingValues. (I'll later re-add it as content padding, but that's easy enough).

Something like:

Scaffold(
    topBar = { ... },
) { paddingWithInset ->
    LazyColumn(
        modifier = Modifier.padding(paddingWithInset.exceptBottomPadding()),
        contentPadding = PaddingValues(bottom = paddingWithInset.calculateBottomPadding())
    ) {
        ...
    }
}

I tried just applying the complete paddingWithInset as contentPadding, but that butchers the overscrollEffect


Edit

The exceptBottomPadding can ofc. be made a composable, which allows accessing the LocalLayoutDirection. However, this still feels clumsy.

@Composable
fun PaddingValues.exceptBottomPadding(): PaddingValues {
    val layoutDirection = LocalLayoutDirection.current

    return PaddingValues(
        top = calculateTopPadding(),
        bottom = 0.dp,
        end = calculateEndPadding(layoutDirection),
        start = calculateStartPadding(layoutDirection)
    )
}

Solution

  • I did a generic extension function:

        @Composable
        fun PaddingValues.copy(
            start: Dp? = null,
            top: Dp? = null,
            end: Dp? = null,
            bottom: Dp? = null
        ): PaddingValues {
            val layoutDirection = LocalLayoutDirection.current
            return PaddingValues(
                start = start ?: this.calculateStartPadding(layoutDirection),
                top = top ?: this.calculateTopPadding(),
                end = end ?: this.calculateEndPadding(layoutDirection),
                bottom = bottom ?: this.calculateBottomPadding(),
            )
        }
    

    And I use it like this:

    Column(paddingValues = it.copy(bottom = 0.dp))