56

Supporting different screen sizes on Android with Jetpack Compose

 3 years ago
source link: https://proandroiddev.com/supporting-different-screen-sizes-on-android-with-jetpack-compose-f215c13081bd
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Supporting different screen sizes on Android with Jetpack Compose

In this post, we are going to discover the pitfalls of using hard-coded dimensions and a way to support different screen sizes.

Rooms, an app built with Jetpack Compose — dimensions case study.

Since the early days of Android, it has been recommended to use Density-independent pixel (abbreviated dp or dip) instead of Pixels for creating layouts and UI elements. Dp helps in creating layouts on multiple screen sizes with different densities easier and more manageable.

“Dp is a virtual pixel unit that takes the same amount of space as 1 pixel on 160 dpi (mdpi) screen.” — Android Design Bytes, gift that keeps on giving ❤

That means 50dp will take roughly the same amount of physical real world space on a Pixel 5 and on a Nexus One, roughly the size of a finger tip. But if you think about it, we have much less space on smaller devices (regardless of the density) as they are, as you guessed, smaller. Yet we use the same set of dimensions for those devices as our latest and biggest devices.

The Problem — Same dimensions on Nexus One and Pixel 5

1*x8VUjgPCm7CmV0OpMK_3jQ.png?q=20
supporting-different-screen-sizes-on-android-with-jetpack-compose-f215c13081bd
Here’s the same screen using the same dimensions on Nexus One (left) and Pixel 5 (right).

Here we can see that while the screen looks pretty neat on a Pixel 5, it looks quite bad on a smaller device. The padding takes a considerable proportion of the space, the text size is way too big, and there’s not enough space left for the button so it gets cropped. Even though the screenshot on the post doesn’t look too shabby, it leaves a lot to be desired when experienced on an actual device. Obviously we can make the screen scroll-able and that would be fine for most apps but we want to do better, don’t we? 🤓

In the screenshot above, we had been using Dimensions by creating a Dimens object with all the app specific dimensions in one place.

Initial dimensions approach

Although this allowed us to define dimensions in Kotlin, we did not take advantage of resource configurations as individual dimensions have the same values for all the screen sizes and configurations.

For instance, Dimens.grid_1 will always be 8.dp regardless of the screen size.

We can take inspiration from the way colors are set in the Theme that allows apps to support multiple themes with relative ease. The idea is to provide values based on a certain configuration, let’s see how colors are setup and how do they update when the theme is updated.

We define two Colors objects LightThemeColors and DarkThemeColors and based on the darkTheme flag one of them is provided to the CompositionLocal.

Colors provided to CompositionLocal based on darkTheme flag

To use colors in the composable screens reference them through the theme object.

Color of the progress bar would be the one set as onBackground in the selected theme

Similarly, we can define dimensions for different configurations and take advantage of smallest width configurations. We can define a default set of dimensions and one for devices with shortest width of at least 360dp.

This is similar to defining two different dimens.xml files in res/values and res-values-sw360dp. This forces us to define all the non default dimensions for different configurations at compile time. With the xml approach, we do not get these checks, easily anyway.

Note that we can also define dimensions with a default value like minimum_touch_target = 48.dp

Now, we have defined both sets of dimensions but how does the system know which one to use? We use CompositionLocal and provide dimensions based on the current configuration.

As you can see, we provide smallDimensions for small devices and sw360Dimensions for devices with screenWidthDp of at least 360. We can also define multiple typography objects with different font sizes in the same way. Dimensions can now be referenced through the theme object as shown below.

And now our screen looks much better on a Nexus One!

1*Thyz9zOg98lKZwTkwC462g.png?q=20
supporting-different-screen-sizes-on-android-with-jetpack-compose-f215c13081bd
A classic before and after screenshot for effect! 😎

If you are migrating the app from the Android View system to Jetpack Compose and don’t want to redefine dimensions again, another approach would be to directly reference the dimensions from xml (using dimensionResource(id=R.dimen.grid_1)) similar to how strings are used in Compose. You would have to define multiple sets of dimensions in res/values and res/values-sw360dp to have the desired result.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK