Exploring Jetpack Compose: Padding Modifier



This image has an empty alt attribute; its file name is banner.png

This post is sponsored by Practical Jetpack Compose.


When it comes to the composition of composables, we may want to apply additional spacing to a composables size constraints. For this we can utilise Padding – padding adds this additional space to the specified sides of the composable, essentially making it larger in size. This area of padding cannot be consumed by the content inside of the composable, instead it merely acts as additional sizing for the composable itself. For example, let’s imagine we have a simple Composable without any padding applied:

The content inside of this composable can span to any of the edges, consuming the whole space that is available. Whilst this might be the desired outcome, when placed in our layout this may end up looking a little odd – so we can use Padding to add some spacing to the composable content. Let’s add some padding to this composable:

Now, with this in place the content of the composable can still only span to the edges of the solid line shown in the image. However, spacing is added around the solid line, spanning to the edges of the dashed line. This area of padding is not consumable by the content of the composable, but the composable itself will consume that area within the UI.


In most cases, padding is used in the form of a modifier, meaning that it can be applied to any composable that we might be working with. The first modifier available is the padding modifier that takes an optional padding argument for each side of the composable:

fun Modifier.padding(
    start: Dp = 0.dp,
    top: Dp = 0.dp,
    end: Dp = 0.dp,
    bottom: Dp = 0.dp
)

This is a flexible modifier as it allows us to apply padding to a defined set of sides – be it a single side or several sides. For example, let’s apply some padding to only the start of the composable:

Modifier.padding(start = 16.dp)

We may also want to apply some padding to the top as well as the start:

Modifier.padding(start = 16.dp, top = 16.dp)

With the padding modifier, only padding will be applied for the edges that we provide values for. If an edge does not have a provided value then the padding will default to 0dp for that edge.

When using this specific padding modifier, it may sometimes be the case that you are only looking to apply equal padding to the vertical and/or horizontal axis. When this is the case, another padding modifier exists that allows you to achieve this.

fun Modifier.padding(
    horizontal: Dp = 0.dp,
    vertical: Dp = 0.dp
)

Here we may want to only apply padding on one of the axis:

Modifier.padding(horizontal = 16.dp)

Or we may want to provide padding to both axis:

Modifier.padding(horizontal = 16.dp, vertical = 6.dp)

There may be cases where we wish to apply padding to every edge of the composable. Here we can use the padding modifier that takes an all argument – the provided padding value will be applied to every edge of the composable:

fun Modifier.padding(all: Dp)

Modifier.padding(16.dp)


With the above padding approaches, right-to-left layouts are accounted for – we can see this via the use of the start and end arguments. However, in some cases we may wish to apply padding without this awareness of righ-to-left layouts. For this we can utilise the absolutePadding modifier – this allows us to define padding values for all edges of a composable, specifically the left and right edges instead of the start and end:

fun Modifier.absolutePadding(
    left: Dp = 0.dp,
    top: Dp = 0.dp,
    right: Dp = 0.dp,
    bottom: Dp = 0.dp
)

Under the hood, the absolutePadding and padding modifiers user the same Modifier class to construct the composable padding. The main difference being the value that is provided for the rtlAware argument – for absolutePadding this value is provided as false, whereas the default padding modifier provides this as true.

private data class PaddingModifier(
    val start: Dp = 0.dp,
    val top: Dp = 0.dp,
    val end: Dp = 0.dp,
    val bottom: Dp = 0.dp,
    val rtlAware: Boolean
)


Alongside the above approaches for applying padding, there is a padding modifier which takes a reference to the PaddingValues class:

fun Modifier.padding(padding: PaddingValues)


@Stable
data class PaddingValues(
    val start: Dp = 0.dp,
    val top: Dp = 0.dp,
    val end: Dp = 0.dp,
    val bottom: Dp = 0.dp
)

Under the hood, this modifier utilises the exact same PaddingModifier class as the other padding modifier functions – meaning that setting an PaddingValues in this way is the same as using the Modifier.padding(all: Dp) function. The PaddingValues class itself is an argument that can be passed to certain composables (Scaffold and Button are to name a few) – this allows you to add padding directly to the content area of the composable without needed to directly apply modifiers. However, whilst this is available to still used via a modifier for other composables, readability is likely improved by the use of other padding modifiers that are available.