Support different screen sizes

Android devices come in all shapes and sizes, so your app's layout needs to be flexible. That is, instead of defining your layout with rigid dimensions that assume a certain screen size and aspect ratio, your layout should gracefully respond to different screen sizes and orientations.

By supporting as many screens as possible, your app can be made available to the greatest number of users with different devices, using a single APK. Additionally, making your app flexible for different screen sizes ensures that your app can handle window configuration changes on the device, such as when the user enables multi-window mode.

This page shows you how to support different screen sizes with the following techniques:

  • Use view dimensions that allow the layout to resize
  • Create alternative UI layouts according to the screen configuration
  • Provide bitmaps that can stretch with the views

But be aware that adapting to different screen sizes doesn't necessarily make your app compatible with all Android form factors. You should take additional steps to support Android Wear, TV, Auto, and Chrome OS devices.

For design guidelines for building UI for different screens, see the material guidelines for responsive UI.

Create a flexible layout

No matter what hardware profile you want to support first, you need to create a layout that is responsive to even small variations in screen size.

Use ConstraintLayout

The best way to create a responsive layout for different screen sizes is to use ConstraintLayout as the base layout in your UI. ConstraintLayout allows you to specify the position and size for each view according to spatial relationships with other views in the layout. This way, all the views can move and stretch together as the screen size changes.

The easiest way to build a layout with ConstraintLayout is to use the Layout Editor in Android Studio. It allows you to drag new views to the layout, attach their constraints to the parent view and other sibling views, and edit the view's properties, all without editing any XML by hand (see figure 1).

For more information, see Build a Responsive UI With ConstraintLayout.

Figure 1. The Layout Editor in Android Studio showing a ConstraintLayout file

But ConstraintLayout won't solve every layout scenario (especially for dynamically-loaded lists, for which you should use RecyclerView), but no matter what layout you use, you should always avoid hard-coding layout sizes (see the next section).

Avoid hard-coded layout sizes

To ensure that your layout is flexible and adapts to different screen sizes, you should use "wrap_content" and "match_parent" for the width and height of most view components, instead of hard-coded sizes.

"wrap_content" tells the view to set its size to whatever is necessary to fit the content within that view.

"match_parent" makes the view expand to as much as possible within the parent view.

For example:

    android:text="@string/lorem_ipsum" />

Although the actual layout for this view depends on other attributes in its parent view and any sibling views, this TextView intends to set its width to fill all available space (match_parent) and set its height to exactly as much space is required by the length of the text (wrap_content). This allows the view to adapt to different screen sizes and different lengths of text.

Figure 2 shows how the width of the text view using "match_parent" adjusts as the screen width changes with device orientation.

Figure 2. A flexible text view

If you're using a LinearLayout, you can also expand the child views with layout weight so that each view fills the remaining space proportional to their weight value. However, using weights in a nested LinearLayout requires the system to perform multiple layout passes to determine the size for each view, slowing your UI performance. Fortunately, ConstraintLayout can achieve nearly all layouts possible with LinearLayout without the performance impacts, so you should try converting your layout to ConstraintLayout. Then, you can define weighted layouts with constraint chains.

Create alternative layouts

Although your layout should always respond to different screen sizes by stretching the space within and around its views, that might not provide the best user experience for every screen size. For example, the UI you designed for a phone, probably doesn't offer a good experience on a tablet. Therefore, your app should also provide alternative layout resources to optimize the UI design for certain screen sizes.

Figure 3. The same app on different screen sizes uses a different layout for each

You can provide screen-specific layouts by creating additional res/layout/ directories—one for each screen configuration that requires a different layout—and then append a screen configuration qualifier to the layout directory name (such as layout-w600dp for screens that have 600dp of available width).

These configuration qualifiers represent the visible screen space available for your app UI. The system takes into account any system decorations (such as the navigation bar) and window configuration changes (such as when the user enables multi-window mode) when selecting the layout from your app.

To create an alternative layout in Android Studio (using version 3.0 or higher), proceed as follows:

  1. Open your default layout and then click Orientation for Preview in the toolbar.
  2. In the drop-down list, click to create a suggested variant such as Create Landscape Variant or click Create Other.
  3. If you selected Create Other, the Select Resource Directory appears. Here, select a screen qualifier on the left and add it to the list of Chosen qualifiers. When you're done adding qualifiers, click OK. (See the following sections for information about screen size qualifiers.)

This creates a duplicate layout file in the appropriate layout directory so you can begin customizing the layout for that screen variant.

Use the smallest width qualifier

The "smallest width" screen size qualifier allows you to provide alternative layouts for screens that have a minimum width measured in density-independent pixels(dp or dip).

By describing the screen size as a measure of density-independent pixels, Android allows you to create layouts that are designed for very specific screen dimensions while avoiding any concerns you might have about different pixel densities.

For example, you can create a layout named main_activity that's optimized for handsets and tablets by creating different versions of the file in directories as follows:

res/layout/main_activity.xml           # For handsets (smaller than 600dp available width)
res/layout-sw600dp/main_activity.xml   # For 7” tablets (600dp wide and bigger)

The smallest width qualifier specifies the smallest of the screen's two sides, regardless of the device's current orientation, so it's a simple way to specify the overall screen size available for your layout.

Here's how other smallest width values correspond to typical screen sizes:

  • 320dp: a typical phone screen (240x320 ldpi, 320x480 mdpi, 480x800 hdpi, etc).
  • 480dp: a large phone screen ~5" (480x800 mdpi).
  • 600dp: a 7” tablet (600x1024 mdpi).
  • 720dp: a 10” tablet (720x1280 mdpi, 800x1280 mdpi, etc).

Figure 4 provides a more detailed view of how different screen dp widths generally correspond to different screen sizes and orientations.

Figure 4. Recommended width breakpoints to support different screen sizes

Remember that all the figures for the smallest width qualifier are density-independent pixels, because what matters is the amount of screen space available after the system accounts for pixel density (not the raw pixel resolution).

Use the available width qualifier

Instead of changing the layout based on the smallest width of the screen, you might want to change your layout based on how much width or height is currently available. For example, if you have a two-pane layout, you might want to use that whenever the screen provides at least 600dp of width, which might change depending on whether the device is in landscape or portrait orientation. In this case, you should use the "available width" qualifier as follows:

res/layout/main_activity.xml         # For handsets (smaller than 600dp available width)
res/layout-w600dp/main_activity.xml  # For 7” tablets or any screen with 600dp
                                     #   available width (possibly landscape handsets)

If the available height is a concern for you, then you can do the same using the "available height" qualifier. For example, layout-h600dp for screens with at least 600dp of screen height.

Add orientation qualifiers

Although you may be able to support all size variations using only combinations of the "smallest width" and "available width" qualifiers, you might also want to change the user experience when the user switches between portrait and landscape orientations.

For that you can add the port or land qualifiers to your resource directory names. Just be sure these come after the other size qualifiers. For example:

res/layout/main_activity.xml                # For handsets
res/layout-land/main_activity.xml           # For handsets in landscape
res/layout-sw600dp/main_activity.xml        # For 7” tablets
res/layout-sw600dp-land/main_activity.xml   # For 7” tablets in landscape

For more information about all the screen configuration qualifiers, see table 2 in the guide to Providing Resources.

Modularize UI components with fragments

When designing your app for multiple screen sizes you want to make sure you aren't needlessly duplicating your UI behavior across your activities. So you should use fragments to extract your UI logic into separate components. Then, you can then combine fragments to create multi-pane layouts when running on a large screen or place in separate activities when running on a handset.

For example, a news app on a tablet might show a list of articles on the left side and a full article on the right side—selecting an article on the left updates the article view on the right. On a handset, however, these two components should appear on separate screens—selecting an article from a list changes the entire screen to show that article.

To learn more, see Building a Dynamic UI with Fragments.

Support Android 3.1 with legacy size qualifiers

If your app supports Android 3.1 (API level 12) or lower, you need to use the legacy size qualifiers in addition to the smallest/available width qualifiers from above.

From the example above, if you want a two pane layout on larger devices you need to use the "large" configuration qualifier to support version 3.1 and lower. So, to implement these layouts on those older versions, you might have the following files:

res/layout/main_activity.xml           # For handsets (smaller than 640dp x 480dp)
res/layout-large/main_activity.xml     # For small tablets (640dp x 480dp and bigger)
res/layout-xlarge/main_activity.xml    # For large tablets (960dp x 720dp and bigger)

Use layout aliases

When supporting both pre- and post-3.2 Android versions you have to use both the smallest-width and large qualifiers for your layouts. So, you would have a file named res/layout-large/main.xml which might be identical to res/layout-sw600dp/main.xml.

To avoid this duplication of the same file, you can use alias files. For example, you can define the following layouts:

res/layout/main.xml            # single-pane layout
res/layout/main_twopanes.xml   # two-pane layout

And add these two files:

  • res/values-large/layout.xml:
        <item name="main" type="layout">@layout/main_twopanes</item>
  • res/values-sw600dp/layout.xml:
        <item name="main" type="layout">@layout/main_twopanes</item>

These two files have identical content, but they don’t actually define the layout. They merely set up main to be an alias to main_twopanes. Since these files have large and sw600dp selectors, they are applied to large screens regardless of Android version (pre-3.2 tablets and TVs match large, and post-3.2 will match sw600dp).

Create stretchable nine-patch bitmaps

If you use a bitmap as the background in a view that changes size, you will notice Android scales your images as the view grows or shrinks based on the size of the screen or content in the view. This often leads to visible blurring or other scaling artifacts. The solution is using nine-patch bitmaps, which are specially formatted PNG files that indicate which areas can and cannot be stretched.

A nine-patch bitmap is basically a standard PNG file, but with an extra 1px border that indicates which pixels should be stretched (and with a .9.png extension instead of just .png). As shown in figure 5, the intersection between the black lines on the left and top edge is the area of the bitmap that can be stretched.

Optionally, you can also define the safe region where content should go inside the view by similarly adding lines on the right and bottom edges.

Figure 5. A nine-patch image (button.9.png)

When you apply a nine-patch as the background to a view, the framework stretches the image correctly to accommodate the size of the button.

For help creating a nine-patch image from a bitmap, see Create Resizable Bitmaps.

Test on all screen sizes

It's important to test your app on a variety of screen sizes so you can ensure your UI scales correctly. If you don't have access to physical devices for all the different screen sizes, you can use the Android Emulator to emulate any screen size.

If you would rather test on a physical device, but don't want to buy the devices, you can use Firebase Test Lab to access devices in a Google data center.

Declare specific screen size support

If you decide that you don't want your app to run at certain screen sizes, you can set limits for how much your screen should resize or even restrict which devices can install your app based on their screen configuration. For more information, see Declare Restricted Screen Support.