Why provide multiple drawables for various densities?

print
There are several reasons to used prescaled drawables:

  1. Scaling down to lower resolutions takes resources (CPU time, memory and it drains your battery faster), especially if you have a lot of images this might be undesired.
  2. Scaling down a large image might result in worse quality than using a ‘pre-tuned’ smaller image. Especially if your images are based on a vector original. Or they contain very fine lines or details, which will get lost when due to the scaling.
    For example:
    original image becomes scaled image
    See here for the source of these images and more information on scaling artifacts.
  3. On lower resolutions the image pixels are larger (or the image gets smaller), so it might be required to remove certain aspects of the image to keep it clear/understandable.

 

Pixel densities


pixel density is the number of pixels within a physical area of the screen and is referred to as dpi (dots per inch). This is different from the resolution, which is the total number of pixels on a screen.

Figure 2. An exaggeration of two device that are the same size but have different pixel densities

Density independence

Your app achieves “density independence” when it preserves the physical size (from the user’s point of view) of your UI design when displayed on screens with different pixel densities (as shown in figure 2). Maintaining density independence is important because, without it, a UI element (such as a button) might appear larger on a low-density screen and smaller on a high-density screen (because when the pixels are larger—as shown in figure 2—a few pixels can go a long way).

The Android system helps you achieve density independence by providing density-independent pixels (dp or dip) as a unit of measurement that you should use instead of pixels (px).

 

https://developer.android.com/training/multiscreen/screendensities.html#TaskProvideAltBmp

 

Provide alternative bitmaps


To provide good graphical qualities on devices with different pixel densities, you should provide multiple versions of each bitmap in your app—one for each density bucket, at a corresponding resolution. Otherwise, Android must scale your bitmap so it occupies the same visible space on each screen, resulting in scaling artifacts such as blurring.

Figure 1. Relative sizes for bitmaps at different density sizes

There are sevaral density buckets available for use in your apps. Table 1 describes the different configuration qualifiers available and what screen types they apply to.

Table 1. Configuration qualifiers for different pixel densities.

Density qualifier Description
ldpi Resources for low-density (ldpi) screens (~120dpi).
mdpi Resources for medium-density (mdpi) screens (~160dpi). (This is the baseline density.)
hdpi Resources for high-density (hdpi) screens (~240dpi).
xhdpi Resources for extra-high-density (xhdpi) screens (~320dpi).
xxhdpi Resources for extra-extra-high-density (xxhdpi) screens (~480dpi).
xxxhdpi Resources for extra-extra-extra-high-density (xxxhdpi) uses (~640dpi).
nodpi Resources for all densities. These are density-independent resources. The system does not scale resources tagged with this qualifier, regardless of the current screen’s density.
tvdpi Resources for screens somewhere between mdpi and hdpi; approximately 213dpi. This is not considered a “primary” density group. It is mostly intended for televisions and most apps shouldn’t need it—providing mdpi and hdpi resources is sufficient for most apps and the system will scale them as appropriate. If you find it necessary to provide tvdpi resources, you should size them at a factor of 1.33*mdpi. For example, a 100px x 100px image for mdpi screens should be 133px x 133px for tvdpi.

To create alternative bitmap drawables for different densities, you should follow the 3:4:6:8:12:16 scaling ratio between the six primary densities. For example, if you have a bitmap drawable that’s 48×48 pixels for medium-density screens, all the different sizes should be:

  • 36×36 (0.75x) for low-density (ldpi)
  • 48×48 (1.0x baseline) for medium-density (mdpi)
  • 72×72 (1.5x) for high-density (hdpi)
  • 96×96 (2.0x) for extra-high-density (xhdpi)
  • 144×144 (3.0x) for extra-extra-high-density (xxhdpi)
  • 192×192 (4.0x) for extra-extra-extra-high-density (xxxhdpi)

Then, place the generated image files in the appropriate subdirectory under res/ and the system will pick the correct one automatically based on the pixel density of the device your app is running on:

res/
  drawable-xxxhdpi/
    awesome-image.png
  drawable-xxhdpi/
    awesome-image.png
  drawable-xhdpi/
    awesome-image.png
  drawable-hdpi/
    awesome-image.png
  drawable-mdpi/
    awesome-image.png

Then, any time you reference @drawable/awesomeimage, the system selects the appropriate bitmap based on the screen’s dpi. If you don’t provide a density-specific resource for that density, the system picks the next best match and scales it to fit the screen.

Tip: If you have some drawable resources that the system should never scale (perhaps because you perform some adjustments to the image yourself at runtime), you should place them in a directory with the nodpi configuration qualifier. Resources with this qualifier are considered density-agnostic and the system will not scale them.

For more information about other configuration qualifiers and how Android selects the appropriate resources for the current screen configuration, see Providing Resources.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.