In the world of Compose, there are a vast range of modifiers that are available at our disposable. As you build more and more UI with Compose, it’s likely that you’re going to discover new modifiers that you previously were not aware of. For me this week it was the aspectRatio modifier – so in this post, we’re going to take a quick dive into what this is and how we can make use of it in our projects.
Looking to learn Jetpack Compose? Check out my course, Practical Jetpack Compose
When it come to sizing of composables, we often turn to constraining dimensions using any of the various size modifiers (width, height, size etc) or filling the any of the available dimensions (fillMaxSize, fillMaxHeight, fillMaxWidth etc). However, these aren’t always going to satisfy our requirements as we may wish to size our composable in other ways based on the constraints of parent containers.
For example, let’s imagine we have an application that allows you to select an image from the device gallery, to then be displayed as filling the available width of the screen space:
Here we are using the fillMaxWidth modifier to fill the available space, and our height is automatically wrapping the available size of the content. However, this is taking up a lot of screen estate – and due to this just being a small preview of the media item, we don’t need it to take up so much space within our UI. We want to reduce the height shown, so we can try fixing the height to reduce the space it takes up.
While this looks OK here, this magic value will only work for media items of this height or greater – if we attach a media item that is shorter than this, we risk taking up more space in the screen than is actually required. We could reduce the height constraint, but then this will end up greatly reducing the height for larger media items. An alternative could be utilising the heightIn modifier to allow only a maximum available height for the image and while this works for this given example, we can’t guarantee consistency for different images that are attached in our app.
To find a simple solution that will work across media dimensions, we’re going to use a fixed ratio for all media items that are displayed here. We want to continue filling the maximum width that is available, but this time we’ll want to constrain the height to match the width of the parent container so that we are constraining the dimensions to a ratio. For this, we can utilise the aspectRatio modifier, which allows us to enforce an aspect ratio when it comes to the sizing of our composable.
matchHeightConstraintsFirst: Boolean = false
When using this modifier, we need to provide the ratio that is to be applied to the composable. This ratio will then be used to to apply the sizing constraint to the composable. When doing so, by default the current width constraints of the composable are prioritised over any widths. If you wish to override this, you can provide a true flag for the matchHeightConstraintsFirst argument which will cause the height constraints to be prioritised. Because in this example we are constraining to the width of our parent, we do not need to utilise this flag.
We can see now that our image is being constrained to an aspect ratio of 1, giving us a square representation for our image. This will be consistent across any images that are being selected in our app, cropping the image to fit into the specified aspect ratio.
When using this modifier, we can apply any aspect ratio that we wish to constrain our composable to. For example, i’ll apply a ratio of 1.4 to the same composable that we saw in the previous example.
As we can see from this quick example, the aspectRatio modifier allows us to constrain our composable to a specified aspect ratio, allowing us to create greater consistency when it comes to unpredictable child sizing in the body of our composables. While I’ve provided an example use case of this, there are likely other scenarios where the aspectRatio modifier can be applied – if you’re utilising it in your apps, do share how!