Supporting Multiple Screens(支持Android各種屏幕尺寸)

原文鏈接

本文翻譯自Supporting Multiple Screens.
目前我這篇翻譯應該是最全,最完整的官方文檔翻譯,轉載我的翻譯請聯繫本人,標明出處.

Supporting Multiple Screens

Android runs on a variety of devices that offer different screen sizes and densities. For applications, the Android system provides a consistent development environment across devices and handles most of the work to adjust each application’s user interface to the screen on which it is displayed. At the same time, the system provides APIs that allow you to control your application’s UI for specific screen sizes and densities, in order to optimize your UI design for different screen configurations. For example, you might want a UI for tablets that’s different from the UI for handsets.

Android系統運行在不同屏幕尺寸和屏幕密度的設備上.對於Android應用程序來說,Android系統在不同設備上提供了統一的開發環境,大部分工作是在調整應用程序需要顯示的界面上的用戶UI.與此同時,Android系統提供了API允許你單獨控制在特定屏幕和分辨率設備下的UI顯示.例如,在你的應用程序裏,你可以爲平板電腦和手機提供不同的UI顯示.

Although the system performs scaling and resizing to make your application work on different screens, you should make the effort to optimize your application for different screen sizes and densities. In doing so, you maximize the user experience for all devices and your users believe that your application was actually designed for their devices—rather than simply stretched to fit the screen on their devices.

儘管Android系統可以在不同的屏幕上縮放、調整應用的UI,但是應用開發人員還是應該儘量的優化UI顯示,並適配UI到不同的屏幕尺寸和分辨率的屏幕上.這樣做時,你才能讓用戶相信你的應用就是針對他們而設計的,而不是簡單的拉伸應用UI界面來適配用戶的手機屏幕.

By following the practices described in this document, you can create an application that displays properly and provides an optimized user experience on all supported screen configurations, using a single .apk file.

按照本文的適配方法,通過一個apk文件,可以創建一個能夠正確適配各種屏幕的應用程序並且能夠提升用戶的使用體驗.


Overview of Screens Support(屏幕支持概述)

This section provides an overview of Android’s support for multiple screens, including: an introduction to the terms and concepts used in this document and in the API, a summary of the screen configurations that the system supports, and an overview of the API and underlying screen-compatibility features.

本節爲Android多屏幕適配概述.包括:介紹本文中API用到的術語和概念,總結系統支持的屏幕配置,API概覽和介紹屏幕兼容特性.

Terms and concepts(術語和概念)

Screen size

  • Actual physical size, measured as the screen’s diagonal.
    For simplicity, Android groups all actual screen sizes into four generalized sizes: small, normal, large, and extra-large

屏幕尺寸

屏幕實際的物理尺寸,是按照屏幕對角線計量的.
爲了簡單起見,Android將所有屏幕劃分爲四種廣義的尺寸:小、標準、大和超大.

Screen density

  • The quantity of pixels within a physical area of the screen; usually referred to as dpi (dots per inch). For example, a “low” density screen has fewer pixels within a given physical area, compared to a “normal” or “high” density screen.
    For simplicity, Android groups all actual screen densities into six generalized densities: low, medium, high, extra-high, extra-extra-high, and extra-extra-extra-high.

屏幕密度

屏幕每英寸的像素點數,通常也被簡稱爲dpi(每英寸像素點數).例如,與標準和高密度的屏幕相比,低密度屏幕在每英寸中具有較少的像素點.
爲了簡單起見,Android也將屏幕密度劃分爲六種廣義密度:low,medium,high,extra-high,extra-extra-high和extra-extra-extra-high.

Orientation

  • The orientation of the screen from the user’s point of view. This is either landscape or portrait, meaning that the screen’s aspect ratio is either wide or tall, respectively. Be aware that not only do different devices operate in different orientations by default, but the orientation can change at runtime when the user rotates the device.

屏幕方向

屏幕方向取決於用戶的角度.無論是橫向或者縱向,分別指的是屏幕的縱橫比例.需要注意的是,不僅是不同的設備有不同的運行方向,同一臺設備用戶在使用過程中因爲旋轉設備也可能會改變屏幕方向.

Resolution

  • The total number of physical pixels on a screen. When adding support for multiple screens, applications do not work directly with resolution; applications should be concerned only with screen size and density, as specified by the generalized size and density groups.

屏幕分辨率

屏幕上的像素總數.當應用需要支持各種屏幕尺寸時,應用不需要關心屏幕的分辨率,而應該關心屏幕的尺寸和屏幕密度.

Density-independent pixel (dp)
A virtual pixel unit that you should use when defining UI layout, to express layout dimensions or position in a density-independent way.
The density-independent pixel is equivalent to one physical pixel on a 160 dpi screen, which is the baseline density assumed by the system for a “medium” density screen. At runtime, the system transparently handles any scaling of the dp units, as necessary, based on the actual density of the screen in use. The conversion of dp units to screen pixels is simple: px = dp * (dpi / 160). For example, on a 240 dpi screen, 1 dp equals 1.5 physical pixels. You should always use dp units when defining your application’s UI, to ensure proper display of your UI on screens with different densities.

密度無關像素

在定義UI佈局時應該使用的密度無關像素單位.
1dp等於160dpi屏幕上的1像素,此屏幕爲mdpi的屏幕.在應用程序運行時,系統會根據不同密度的屏幕處理dp的大小.dp轉px的公式爲:px = dp * (dpi / 160).例如,在240dpi的屏幕上,1dp=1.5px.定義應用UI佈局時,你應該總是使用dp單位,以確保在不同密度的屏幕上都能正確顯示你的UI佈局.

Range of screens supported(支持的屏幕範圍)

Starting with Android 1.6 (API Level 4), Android provides support for multiple screen sizes and densities, reflecting the many different screen configurations that a device may have. You can use features of the Android system to optimize your application’s user interface for each screen configuration and ensure that your application not only renders properly, but provides the best user experience possible on each screen.

從Android1.6(API等級4)開始,Android已經提供了對不同屏幕尺寸和屏幕密度的支持,因爲一個設備型號可能會有不同的屏幕配置.你可以利用Android系統的這些特性爲每一個屏幕配置優化你的應用程序界面,確保你的應用程序不僅能正確的運行,而且還能儘可能在每一種屏幕上提供更好的用戶體驗.

To simplify the way that you design your user interfaces for multiple screens, Android divides the range of actual screen sizes and densities into:

  • A set of four generalized sizes: small, normal, large, and xlarge
  • A set of six generalized densities:
    • ldpi (low) ~120dpi
    • mdpi (medium) ~160dpi
    • hdpi (high) ~240dpi
    • xhdpi (extra-high) ~320dpi
    • xxhdpi (extra-extra-high) ~480dpi
    • xxxhdpi (extra-extra-extra-high) ~640dpi

爲了簡化多屏幕的UI適配,Android系統按照屏幕尺寸和屏幕密度劃分爲:

四種廣義屏幕尺寸:小、標準、大,超大
六種廣義屏幕密度:

ldpi(low) ~ 120dpi
mdpi(medium) ~ 160dpi
hdpi(high) ~ 240dpi
xhdpi(extra-high) ~ 320dpi
xxhdpi(extra-extra-high) ~ 480dpi
xxxhpi(extra-extra-extra-high) ~ 640dpi

The generalized sizes and densities are arranged around a baseline configuration that is a normal size and mdpi (medium) density. This baseline is based upon the screen configuration for the first Android-powered device, the T-Mobile G1, which has an HVGA screen (until Android 1.6, this was the only screen configuration that Android supported).

這種屏幕尺寸和密度的劃分是圍繞一種基準的配置進行劃分的.這種基準配置是指標準尺寸和mdpi的像素密度.這個基準也是基於Android第一款機型,T-Mobile G1,它具有HVGA的屏幕(直到Android1.6,這是Android唯一支持的屏幕配置).

Each generalized size and density spans a range of actual screen sizes and densities. For example, two devices that both report a screen size of normal might have actual screen sizes and aspect ratios that are slightly different when measured by hand. Similarly, two devices that report a screen density of hdpi might have real pixel densities that are slightly different. Android makes these differences abstract to applications, so you can provide UI designed for the generalized sizes and densities and let the system handle any final adjustments as necessary. Figure 1 illustrates how different sizes and densities are roughly categorized into the different size and density groups.

每個屏幕尺寸和屏幕密度的定義都包含了一個範圍.例如,用手測量時,兩個標準的屏幕尺寸的設備可能具有實際的稍微不同的屏幕尺寸和縱橫比.同樣的,兩個同是hdpi像素密度的手機在真正的屏幕像素密度上可能也會有細微的差別.Android系統讓這些差別對於應用程序來說無關,所以你可以爲廣義的屏幕尺寸和密度提供UI設計,讓系統來處理最後的調整.圖1粗略的表明如何按照不同尺寸密度分類成不同的屏幕尺寸和屏幕密度.

android_multiple_screen_1

As you design your UI for different screen sizes, you’ll discover that each design requires a minimum amount of space. So, each generalized screen size above has an associated minimum resolution that’s defined by the system. These minimum sizes are in “dp” units—the same units you should use when defining your layouts—which allows the system to avoid worrying about changes in screen density.

  • xlarge screens are at least 960dp x 720dp
  • large screens are at least 640dp x 480dp
  • normal screens are at least 470dp x 320dp
  • small screens are at least 426dp x 320dp

當你爲不同的屏幕設計UI時,你將會發現每一個設計都需要一個最小的屏幕空間.因此,上面提到的每一種屏幕尺寸都有系統定義的相關聯的最小分辨率.這些最小尺寸使用dp爲單位,和你定義UI的單位相同,這樣使得系統能避免不同屏幕密度下的顯示效果不一致.

超大屏幕至少960dp x 720dp
大屏幕至少640dp x 480dp
標準屏幕至少470dp x 320dp
小屏幕至少426dp x 320dp

To optimize your application’s UI for the different screen sizes and densities, you can provide alternative resources for any of the generalized sizes and densities. Typically, you should provide alternative layouts for some of the different screen sizes and alternative bitmap images for different screen densities. At runtime, the system uses the appropriate resources for your application, based on the generalized size or density of the current device screen.

爲了在不同的屏幕尺寸和屏幕密度的設備上優化你的應用UI,你應該爲不同的屏幕尺寸和密度提供不同的顯示資源.一般開發人員都需要在同一款應用中爲不同的屏幕尺寸和密度提供不同的佈局文件和圖片資源文件.在Android系統運行時,Android系統會根據當前屏幕的尺寸和密度選擇合適的佈局文件和圖片資源.

You do not need to provide alternative resources for every combination of screen size and density. The system provides robust compatibility features that can handle most of the work of rendering your application on any device screen, provided that you’ve implemented your UI using techniques that allow it to gracefully resize (as described in the Best Practices, below).

在應用開發中,沒必要爲每一種屏幕尺寸和屏幕密度的組合提供不同的資源.Android系統會提供很強大的兼容性,只要你遵循這裏描述的最佳實踐,Android系統就能夠處理大多數的情況了.

Density independence(密度無關性)

Your application achieves “density independence” when it preserves the physical size (from the user’s point of view) of user interface elements when displayed on screens with different densities.

你的應用必須在不同密度的設備上,保持UI元素的物理尺寸比例不變(從用戶的角度來看),以實現密度無關的特性.

Maintaining density independence is important because, without it, a UI element (such as a button) appears physically larger on a low-density screen and smaller on a high-density screen. Such density-related size changes can cause problems in your application layout and usability. Figures 2 and 3 show the difference between an application when it does not provide density independence and when it does, respectively.

應用實現密度無關是非常重要的,如果應用無法實現密度無關,例如一個UI控件(像button這種)在低密度的屏幕上會顯得很大,而在高密度的屏幕上又會顯得很小.密度相關會導致你的應用在顯示上出現問題.圖2和圖3分別展示了不提供密度無關性和提供密度無關性時,應用程序的顯示差異.

android_multiple_screen_2

The Android system helps your application achieve density independence in two ways:

  • The system scales dp units as appropriate for the current screen density
  • The system scales drawable resources to the appropriate size, based on the current screen density, if necessary

Android系統通過兩個方式幫助你的應用實現密度無關的特性:

系統會在不同密度的屏幕上動態調整dp代表的像素值.
如有必要,系統會基於當前屏幕密度適配合適大小的圖片資源.

In figure 2, the text view and bitmap drawable have dimensions specified in pixels (px units), so the views are physically larger on a low-density screen and smaller on a high-density screen. This is because although the actual screen sizes may be the same, the high-density screen has more pixels per inch (the same amount of pixels fit in a smaller area). In figure 3, the layout dimensions are specified in density-independent pixels (dp units). Because the baseline for density-independent pixels is a medium-density screen, the device with a medium-density screen looks the same as it does in figure 2. For the low-density and high-density screens, however, the system scales the density-independent pixel values down and up, respectively, to fit the screen as appropriate.

在圖2中,TextView和Bitmap Drawable直接使用px爲度量單位.View在低密度的屏幕上看起來很大,在高密度的屏幕上看起來又比較小.這是因爲不同密度屏幕的每英寸像素數是不一致的.在圖3中,TextView和Bitmap Drawable使用dp這種密度無關的度量單位,因此在不同密度的屏幕上看起來的效果是一致的.

In most cases, you can ensure density independence in your application simply by specifying all layout dimension values in density-independent pixels (dp units) or with “wrap_content”, as appropriate. The system then scales bitmap drawables as appropriate in order to display at the appropriate size, based on the appropriate scaling factor for the current screen’s density.

在大多數情況下,使用dp爲度量單位或者使用wrap_content這種度量屬性可以使你的應用具備屏幕密度無關特性.系統會基於當前屏幕密度使用合適的比例來適當的調整.

However, bitmap scaling can result in blurry or pixelated bitmaps, which you might notice in the above screenshots. To avoid these artifacts, you should provide alternative bitmap resources for different densities. For example, you should provide higher-resolution bitmaps for high-density screens and the system will use those instead of resizing the bitmap designed for medium-density screens. The following section describes more about how to supply alternative resources for different screen configurations.

然而,系統對圖片的調整可能導致圖片顯示的模糊等問題.爲了避免這種問題,你應該爲不同密度的屏幕提供不同的圖片資源.例如,你應該爲hdpi的屏幕提供高分辨率的圖片資源,爲標準屏幕提供標準分辨率的圖片資源,而不是讓系統去根據屏幕密度來進行圖片的調整.接下來的章節主要介紹如何爲不同密度的屏幕提供不同的資源.


How to Support Multiple Screens(如何適配不同規格的屏幕)

The foundation of Android’s support for multiple screens is its ability to manage the rendering of an application’s layout and bitmap drawables in an appropriate way for the current screen configuration. The system handles most of the work to render your application properly on each screen configuration by scaling layouts to fit the screen size/density and scaling bitmap drawables for the screen density, as appropriate. To more gracefully handle different screen configurations, however, you should also:

  • Explicitly declare in the manifest which screen sizes your application supports
    By declaring which screen sizes your application supports, you can ensure that only devices with the screens you support can download your application. Declaring support for different screen sizes can also affect how the system draws your application on larger screens—specifically, whether your application runs in screen compatibility mode.
    To declare the screen sizes your application supports, you should include the <supports-screens> element in your manifest file.

  • Provide different layouts for different screen sizes
    By default, Android resizes your application layout to fit the current device screen. In most cases, this works fine. In other cases, your UI might not look as good and might need adjustments for different screen sizes. For example, on a larger screen, you might want to adjust the position and size of some elements to take advantage of the additional screen space, or on a smaller screen, you might need to adjust sizes so that everything can fit on the screen.
    The configuration qualifiers you can use to provide size-specific resources are small, normal, large, and xlarge. For example, layouts for an extra-large screen should go in layout-xlarge/.
    Beginning with Android 3.2 (API level 13), the above size groups are deprecated and you should instead use the sw<N>dp configuration qualifier to define the smallest available width required by your layout resources. For example, if your multi-pane tablet layout requires at least 600dp of screen width, you should place it in layout-sw600dp/. Using the new techniques for declaring layout resources is discussed further in the section about Declaring Tablet Layouts for Android 3.2.

  • Provide different bitmap drawables for different screen densities
    By default, Android scales your bitmap drawables (.png, .jpg, and .gif files) and Nine-Patch drawables (.9.png files) so that they render at the appropriate physical size on each device. For example, if your application provides bitmap drawables only for the baseline, medium screen density (mdpi), then the system scales them up when on a high-density screen, and scales them down when on a low-density screen. This scaling can cause artifacts in the bitmaps. To ensure your bitmaps look their best, you should include alternative versions at different resolutions for different screen densities.
    The configuration qualifiers (described in detail below) that you can use for density-specific resources are ldpi (low), mdpi (medium), hdpi (high), xhdpi extra-high), xxhdpi (extra-extra-high), and xxxhdpi (extra-extra-extra-high). For example, bitmaps for high-density screens should go in drawable-hdpi/.

Android能夠適配多種屏幕的基礎在於它能根據當前屏幕的參數、配置來決定需要渲染的佈局和圖片資源.Android系統爲了能在不同密度的屏幕上合理的顯示應用,花了大量的工作用來處理佈局和圖片的調整.爲了更好的適配不同的屏幕,應用開發人員應該注意以下幾點:

  • 在你的AndroidManifest文件中聲明應用支持的屏幕尺寸.
    通過這種聲明,你可以保證只有符合屏幕尺寸要求的設備才能下載安裝你的應用.聲明不同尺寸屏幕會影響到系統在屏幕上如何繪製你的App,特別是當你的應用是運行在屏幕兼容模式下.
    在AndroidManifest.xml中,通過”<supports-screens>”標籤來聲明你要支持的屏幕尺寸.
  • 爲不同規格的屏幕提供不同的佈局文件
    默認情況下,Android系統會調整應用佈局來適配當前的屏幕密度.大多數情況下,佈局適配沒有太大問題.但是也有例外,不同屏幕尺寸情況下你的UI可能需要單獨調整.例如,在較大的屏幕上,可能需要調整某些元素的位置和尺寸來充分利用額外的屏幕空間,或者在較小的屏幕上,會調整尺寸使得一切都可以在屏幕上顯示.
    可以使用Android系統提供的大小限定符,有small,normal,large和xlarge.例如,爲超大屏幕適配的佈局文件應該存放在layout-xlarge目錄下.
    從Android3.2(API等級13)開始,上面的尺寸分組已經被棄用,你應該使用sw<N>dp限定符去定義佈局資源需要的最小的可用寬度.例如,如果多窗口的平板佈局至少需要600dp的屏幕寬度,因此你應該把平板的佈局文件存放在layout-sw600dp目錄下.
  • 爲不同密度的屏幕提供不同的圖片資源
    默認情況下,Android系統會自動調整你的圖片資源(.png, .jpg和.gif文件)和.9資源圖片(.9.png文件),以便讓資源在不同密度的屏幕上顯示適當的物理尺寸.例如,如果你的應用中只爲mdpi的標準屏幕提供了一份圖片資源,那麼在hdpi的屏幕上,Android系統會拉伸你的資源,在ldpi的屏幕上,Android系統會壓縮你的資源.因此,爲了確保你的圖片資源看起來正常,你需要爲不同密度的屏幕提供不同的圖片資源.可以用來指定密度資源的限定符有ldpi,mdpi,hdpi,xhdpi,xxhdpi和xxxhdpi.例如,爲hdpi屏幕準備的圖片資源應該存放在drawable-hdpi目錄下.

Note: The mipmap-xxxhdpi qualifier is necessary only to provide a launcher icon that can appear larger than usual on an xxhdpi device. You do not need to provide xxxhdpi assets for all your app’s images.

注意:mipmap-xxxhdpi目錄是爲了在超過xxxhdpi的設備上存放桌面圖標的.你不需要爲應用內所有的圖片都提供xxxhdpi的資源.

At runtime, the system ensures the best possible display on the current screen with the following procedure for any given resource:

  1. The system uses the appropriate alternative resource
    Based on the size and density of the current screen, the system uses any size- and density-specific resource provided in your application. For example, if the device has a high-density screen and the application requests a drawable resource, the system looks for a drawable resource directory that best matches the device configuration. Depending on the other alternative resources available, a resource directory with the hdpi qualifier (such as drawable-hdpi/) might be the best match, so the system uses the drawable resource from this directory.

  2. If no matching resource is available, the system uses the default resource and scales it up or down as needed to match the current screen size and density
    The “default” resources are those that are not tagged with a configuration qualifier. For example, the resources in drawable/ are the default drawable resources. The system assumes that default resources are designed for the baseline screen size and density, which is a normal screen size and a medium-density. As such, the system scales default density resources up for high-density screens and down for low-density screens, as appropriate.
    However, when the system is looking for a density-specific resource and does not find it in the density-specific directory, it won’t always use the default resources. The system may instead use one of the other density-specific resources in order to provide better results when scaling. For example, when looking for a low-density resource and it is not available, the system prefers to scale-down the high-density version of the resource, because the system can easily scale a high-density resource down to low-density by a factor of 0.5, with fewer artifacts, compared to scaling a medium-density resource by a factor of 0.75.

在Android系統運行時,系統通過以下幾個步驟來保證屏幕上有最佳的顯示效果:

  1. 系統選擇合適的資源來顯示
    基於當前屏幕的尺寸和密度,系統會選擇應用程序中合適的資源.例如,在hdpi的設備上,應用程序需要一個圖片資源,這時系統會尋找最適合在hdpi屏幕上顯示的圖片資源,一般會去drawable-hdpi目錄下查找,因爲這個目錄下的資源是最匹配hdpi的屏幕的.
  2. 如果沒有匹配的資源可用,系統會使用默認資源且會拉伸或者壓縮資源來適配當前屏幕的密度和尺寸
    默認資源是指那些存放在沒有被限定符標記的目錄下的資源.例如,在drawable目錄下就是默認的圖片資源.Android系統假定默認資源是爲基準屏幕尺寸和密度設計的,即標準屏幕尺寸和mdpi的屏幕密度.同樣的,系統會爲hdpi的屏幕拉伸默認資源,會爲ldpi的屏幕壓縮默認資源.
    然而,當系統在尋找一個指定密度的資源且在匹配限定符目錄下沒找到它時,系統不一定總是使用默認資源.爲了獲取更好的壓縮或拉伸效果,系統會使用一個其他指定密度的資源.例如,當系統尋找ldpi的資源且沒找到時,系統會優先尋找hdpi的資源然後通過壓縮來使用.因爲系統通過換算,可以輕易知道只需要將hdpi的資源簡單的乘以0.5係數來壓縮即可得到ldpi的資源了.這比使用默認資源乘以0.75係數花費的工作要小很多.

Using configuration qualifiers (使用限定符)

Android supports several configuration qualifiers that allow you to control how the system selects your alternative resources based on the characteristics of the current device screen. A configuration qualifier is a string that you can append to a resource directory in your Android project and specifies the configuration for which the resources inside are designed.

Android系統支持多種限定符,讓你可以控制系統如何基於當前的屏幕尺寸和密度選擇合適的資源.一個限定符是一個字符串,你可以把它附加到你的Android工程的資源目錄上以指定這是特定尺寸和密度的資源目錄.

To use a configuration qualifier:

  1. Create a new directory in your project’s res/ directory and name it using the format: <resources_name>-<qualifier>
    • <resources_name> is the standard resource name (such as drawable or layout).
    • <qualifier> is a configuration qualifier from table 1, below, specifying the screen configuration for which these resources are to be used (such as hdpi or xlarge).
    • You can use more than one <qualifier> at a time—simply separate each qualifier with a dash.
  2. Save the appropriate configuration-specific resources in this new directory. The resource files must be named exactly the same as the default resource files.

使用限定符的方法:

  1. 在res目錄下創建資源目錄,命名方式爲:resources_name-qualifier
    • resources_name是資源目錄名,例如drawable或者layout
    • qualifier是限定符名稱,例如hdpi或者xlarge.
  2. 將相應的資源保存在上面創建的特定目錄中.注意,例如drawable-hdpi的目錄只能放置hdpi的資源圖片,不要放錯了.

For example, xlarge is a configuration qualifier for extra-large screens. When you append this string to a resource directory name (such as layout-xlarge), it indicates to the system that these resources are to be used on devices that have an extra-large screen.

例如,xlarge限定符是爲超大屏幕做的適配標識.當你把xlarge加到相應的目錄後面(例如layout-xlarge),這就意味着當處於超大屏幕時需要會從有xlarge標識的目錄中尋找資源文件.

Table 1. Configuration qualifiers that allow you to provide special resources for different screen configurations.

表格1. 爲應用提供的屏幕尺寸限定符和屏幕密度限定符.

屏幕特性 限定符 描述
屏幕尺寸 small 小屏幕
normal 基準屏幕
large 大屏幕
xlarge 超大屏幕
屏幕密度 ldpi <=120dpi
mdpi <= 160dpi
hdpi <= 240dpi
xhdpi <= 320dpi
xxhdpi <= 480dpi
xxhdpi <= 640dpi(只用來存放icon)
nodpi 與屏幕密度無關的資源.系統不會針對屏幕密度對其中資源進行壓縮或者拉伸
tvdpi 介於mdpi與hdpi之間,特定針對213dpi,專門爲電視準備的,手機應用開發不需要關心這個密度值.
屏幕方向 land 橫向
port 縱向
屏幕寬高比 long 比標準屏幕寬高比明顯的高或者寬的這樣屏幕
notlong 和標準屏幕配置一樣的屏幕寬高比

For example, the following application resource directories provide different layout designs for different screen sizes and different drawables. Use the mipmap/ folders for launcher icons.

以下是應用程序的資源目錄列表.其中mipmap目錄是用來存放應用圖標的.

res/layout/my_layout.xml              // layout for normal screen size ("default")
res/layout-large/my_layout.xml        // layout for large screen size
res/layout-xlarge/my_layout.xml       // layout for extra-large screen size
res/layout-xlarge-land/my_layout.xml  // layout for extra-large in landscape orientation

res/drawable-mdpi/graphic.png         // bitmap for medium-density
res/drawable-hdpi/graphic.png         // bitmap for high-density
res/drawable-xhdpi/graphic.png        // bitmap for extra-high-density
res/drawable-xxhdpi/graphic.png       // bitmap for extra-extra-high-density

res/mipmap-mdpi/my_icon.png         // launcher icon for medium-density
res/mipmap-hdpi/my_icon.png         // launcher icon for high-density
res/mipmap-xhdpi/my_icon.png        // launcher icon for extra-high-density
res/mipmap-xxhdpi/my_icon.png       // launcher icon for extra-extra-high-density
res/mipmap-xxxhdpi/my_icon.png      // launcher icon for extra-extra-extra-high-density

Be aware that, when the Android system picks which resources to use at runtime, it uses certain logic to determine the “best matching” resources. That is, the qualifiers you use don’t have to exactly match the current screen configuration in all cases in order for the system to use them. Specifically, when selecting resources based on the size qualifiers, the system will use resources designed for a screen smaller than the current screen if there are no resources that better match (for example, a large-size screen will use normal-size screen resources if necessary). However, if the only available resources are larger than the current screen, the system will not use them and your application will crash if no other resources match the device configuration (for example, if all layout resources are tagged with the xlarge qualifier, but the device is a normal-size screen). For more information about how the system selects resources, read How Android Finds the Best-matching Resource.

請注意,當Android系統挑選資源時,它採用特定的邏輯來判定”最匹配”資源.這意味着,你使用限定符時不需要非常精確,以便於不同設備上應用程序進行篩選(ps:過於精確會導致系統找不到資源從而報錯).特別需要注意的是,當基於限定符選擇資源時,如果沒有更匹配的資源,系統會使用比當前限定符更小的限定符修飾的資源.但是,如果唯一可用的資源比當前屏幕尺寸還大,系統將不會使用它們,這時可能導致應用程序崩潰.

Designing alternative layouts and drawables(設計可選擇的佈局文件和圖片資源)

The types of alternative resources you should create depends on your application’s needs. Usually, you should use the size and orientation qualifiers to provide alternative layout resources and use the density qualifiers to provide alternative bitmap drawable resources.

應該創建的資源類型取決於應用程序的需要.通常,你需要使用屏幕尺寸和屏幕方向限定符來創建佈局資源目錄,使用屏幕密度限定符來創建圖片資源目錄.

The following sections summarize how you might want to use the size and density qualifiers to provide alternative layouts and drawables, respectively.

下面的章節概要的介紹瞭如何使用尺寸和密度來分別創建佈局目錄和資源目錄.

Alternative layouts(可選佈局)

Generally, you’ll know whether you need alternative layouts for different screen sizes once you test your application on different screen configurations. For example:

  • When testing on a small screen, you might discover that your layout doesn’t quite fit on the screen. For example, a row of buttons might not fit within the width of the screen on a small screen device. In this case you should provide an alternative layout for small screens that adjusts the size or position of the buttons.
  • When testing on an extra-large screen, you might realize that your layout doesn’t make efficient use of the big screen and is obviously stretched to fill it. In this case, you should provide an alternative layout for extra-large screens that provides a redesigned UI that is optimized for bigger screens such as tablets.
  • Although your application should work fine without an alternative layout on big screens, it’s quite important to users that your application looks as though it’s designed specifically for their devices. If the UI is obviously stretched, users are more likely to be unsatisfied with the application experience.
  • And, when testing in the landscape orientation compared to the portrait orientation, you might notice that UI elements placed at the bottom of the screen for the portrait orientation should instead be on the right side of the screen in landscape orientation.

通常情況下,一旦你在不同的屏幕配置上測試你的應用,你就會知道是否需要爲不同的屏幕提供不同的佈局適配了.例如:

  • 當在小屏幕上進行UI測試時, 你可能會發現你的佈局並不適合小屏幕.例如,你有一排的button控件可能在小屏幕上無法展開,這個時候你就需要爲小屏幕單獨適配一個佈局文件.
  • 當在超大屏幕上進行UI測試時,你可能會發現你的佈局並沒有合理的利用超大的佈局空間,而僅僅是通過拉伸來填充它.這種情況下,你應該爲超大屏幕例如平板設備提供一個新的佈局文件來實現更好的佈局.
  • 當豎屏轉爲橫屏時,你可能會注意到爲豎屏設計的被放置在屏幕底部的UI元素在橫屏情況下更應該被放在屏幕右側.

To summarize, you should be sure that your application layout:

  • Fits on small screens (so users can actually use your application)
  • Is optimized for bigger screens to take advantage of the additional screen space
  • Is optimized for both landscape and portrait orientations

總結一下,你應該確保你的應用程序佈局滿足如下三點要求:

  • 適配小屏幕(保證用戶能使用你的應用程序)
  • 利用額外的屏幕空間爲超大屏幕設備做優化
  • 能夠同時很好的支持橫屏和豎屏

If your UI uses bitmaps that need to fit the size of a view even after the system scales the layout (such as the background image for a button), you should use Nine-Patch bitmap files. A Nine-Patch file is basically a PNG file in which you specify two-dimensional regions that are stretchable. When the system needs to scale the view in which the bitmap is used, the system stretches the Nine-Patch bitmap, but stretches only the specified regions. As such, you don’t need to provide different drawables for different screen sizes, because the Nine-Patch bitmap can adjust to any size. You should, however, provide alternate versions of your Nine-Patch files for different screen densities.

如果你的控件UI需要用圖片來填充一個控件尺寸,甚至是在佈局被調整之後(例如button的背景圖),你應該使用.9圖片.因爲.9圖片是一個可以指定特定二維區域被拉伸的png圖片.當系統需要調整帶有圖片的控件時,系統會自動拉伸.9圖片指定的區域.這樣,你就沒必要爲不同的屏幕大小提供不同的圖片資源了,.9的圖片資源幫我們自動進行了調節.

Alternative drawables(可選圖片資源)

Almost every application should have alternative drawable resources for different screen densities, because almost every application has a launcher icon and that icon should look good on all screen densities. Likewise, if you include other bitmap drawables in your application (such as for menu icons or other graphics in your application), you should provide alternative versions or each one, for different densities.

幾乎所有的Android應用程序都需要爲不同密度的屏幕提供不同的圖片資源文件,因爲至少每個應用都有launcher圖標,而launcher圖標需要在不同密度的屏幕上都有很好的顯示.

Note: You only need to provide density-specific drawables for bitmap files (.png, .jpg, or .gif) and Nine-Patch files (.9.png). If you use XML files to define shapes, colors, or other drawable resources, you should put one copy in the default drawable directory (drawable/).

注意:你只需要爲特定的圖片文件(.png,.jpg或者.gif)提供不同屏幕密度的資源.如果你利用xml文件來定義一個shapes,colors等,你是不需要爲xml做不同屏幕密度適配的,你只需要把xml文件放到drawable目錄即可.

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

  • 36x36 (0.75x) for low-density
  • 48x48 (1.0x baseline) for medium-density
  • 72x72 (1.5x) for high-density
  • 96x96 (2.0x) for extra-high-density
  • 144x144 (3.0x) for extra-extra-high-density
  • 192x192 (4.0x) for extra-extra-extra-high-density (launcher icon only; see note above)

爲了給不同的密度的屏幕創建可選擇的圖片資源,你應該按照3:4:6:8:12:16這6種密度比例進行適配.例如,如果你爲mdpi屏幕提供了一個48x48的圖片資源,你同樣需要爲其他密度提供如下圖片資源:

  • 36x36 ldpi
  • 48x48 mdpi
  • 72x72 hdpi
  • 96x96 xhdpi
  • 144x144 xxhdpi
  • 196x196 xxxhdpi

Declaring Tablet Layouts for Android 3.2(適配Android3.2平板佈局)

For the first generation of tablets running Android 3.0, the proper way to declare tablet layouts was to put them in a directory with the xlarge configuration qualifier (for example, res/layout-xlarge/). In order to accommodate other types of tablets and screen sizes—in particular, 7” tablets—Android 3.2 introduces a new way to specify resources for more discrete screen sizes. The new technique is based on the amount of space your layout needs (such as 600dp of width), rather than trying to make your layout fit the generalized size groups (such as large or xlarge).

對於第一代運行在Android3.0上的平板,正確聲明平板佈局的方法是將他們放在xlarge限定符修飾的目錄中(例如,res/layout-xlarge).爲了適應其他類型的平板和屏幕尺寸,尤其是7寸平板,Android3.2爲這些離散的平板尺寸引入了新的限定符.新的限定符是基於你佈局需要的空間設定的(例如:需要600dp的寬度),而不是讓你的佈局去適配廣義的尺寸組(例如:large或者xlarge的屏幕).

The reason designing for 7” tablets is tricky when using the generalized size groups is that a 7” tablet is technically in the same group as a 5” handset (the large group). While these two devices are seemingly close to each other in size, the amount of space for an application’s UI is significantly different, as is the style of user interaction. Thus, a 7” and 5” screen should not always use the same layout. To make it possible for you to provide different layouts for these two kinds of screens, Android now allows you to specify your layout resources based on the width and/or height that’s actually available for your application’s layout, specified in dp units.

爲7寸屏幕設計佈局複雜的原因是:當使用廣義的尺寸組時,7寸的平板和5寸的手機位於同一個尺寸組裏無法區分.很顯然,平板和手機應該使用不同的佈局,因此爲了能夠爲這兩種屏幕提供不同的佈局,Android允許你用dp單位指定你佈局文件在屏幕上需要的寬或高.

For example, after you’ve designed the layout you want to use for tablet-style devices, you might determine that the layout stops working well when the screen is less than 600dp wide. This threshold thus becomes the minimum size that you require for your tablet layout. As such, you can now specify that these layout resources should be used only when there is at least 600dp of width available for your application’s UI.

例如,當你爲平板設備提供了佈局文件之後,你可決定在小於600dp的屏幕上不使用這個佈局文件.這個限制因此變成你平板佈局需要的最小尺寸.在這種情況下,你能指定這些佈局資源被用在至少600dp寬的屏幕上.

You should either pick a width and design to it as your minimum size, or test what is the smallest width your layout supports once it’s complete.

你應該選擇一個寬度作爲你平板佈局設計的最小尺寸,或者一旦設計完成測試你的佈局支持的最小寬度.

Note: Remember that all the figures used with these new size APIs are density-independent pixel (dp) values and your layout dimensions should also always be defined using dp units, because what you care about is the amount of screen space available after the system accounts for screen density (as opposed to using raw pixel resolution). For more information about density-independent pixels, read Terms and concepts, earlier in this document.

注意:所有Android3.2提供的新的API都是使用密度無關像素(dp),你的佈局裏面尺寸也應該用dp爲單位.因爲你關心的應該是考慮屏幕密度後的可用空間,而不是原始像素大小.

Using new size qualifiers(使用新的尺寸限定符)

The different resource configurations that you can specify based on the space available for your layout are summarized in table 2. These new qualifiers offer you more control over the specific screen sizes your application supports, compared to the traditional screen size groups (small, normal, large, and xlarge).

表2裏總結Android3.2之後新增的尺寸限定符.相比傳統的屏幕尺寸組(小,標準,大和超大),這些新的限定符爲你的應用程序在特定的屏幕上提供了更多的支持.

Note: The sizes that you specify using these qualifiers are not the actual screen sizes. Rather, the sizes are for the width or height in dp units that are available to your activity’s window. The Android system might use some of the screen for system UI (such as the system bar at the bottom of the screen or the status bar at the top), so some of the screen might not be available for your layout. Thus, the sizes you declare should be specifically about the sizes needed by your activity—the system accounts for any space used by system UI when declaring how much space it provides for your layout. Also beware that the Action Bar is considered a part of your application’s window space, although your layout does not declare it, so it reduces the space available for your layout and you must account for it in your design.

注意:你使用的這些限定符修飾的尺寸並不是實際的屏幕尺寸,而是你Activity中Window所佔據的屏幕尺寸.Android系統會爲system UI分配一定的屏幕空間(例如屏幕底部的導航欄或者屏幕頂部的狀態欄),所以你的佈局可能不會佔據所有的屏幕空間.因此,你定義的尺寸應該是你activity所需要使用到的尺寸.actionbar被認爲是你應用程序界面的一部分,所以雖然你沒有定義Action Bar,也需要爲你的佈局設計中考慮Action Bar所佔用的空間.

Table 2. configuration qualifiers for screen size (introduced in Android 3.2).

表格2. 新的屏幕尺寸限定符(Android3.2 之後引入)

屏幕特性 限定符 描述
最小寬度限定符 sw<N>dp
例如sw600dp, sw720dp
屏幕的最小尺寸,就是屏幕可用區域的最小尺寸,是指屏幕可用高度或寬度的最小值(你可以默認是屏幕的最小寬度).你能用這個限定符確保,無論屏幕方向如何,這個限定符修飾下的佈局需要的屏幕最小尺寸是Ndp.
例如,如果你的佈局在運行時需要的最小屏幕寬度是600dp,則你可以利用這個限定符創建佈局資源目錄res/layout-sw600dp.只有當屏幕的最小寬度或最小高度是600dp時,系統纔會使用這些佈局文件或者資源文件.最小屏幕寬度是固定設備的特有屏幕尺寸,當屏幕方向發生變化時,設備的最小寬度值不變.
設備的最小寬度值要考慮屏幕的尺寸和系統UI.例如,如果在屏幕上有一些系統持久化UI元素,則系統的最小寬度值要比實現的屏幕尺寸小一些,因爲這些系統的UI元素你的應用是無法使用到的.
當你使用之前的廣義限定符是,你可以定義連續的一系列限定符.用最小寬度來決定廣義屏幕尺寸是有意義的,是因爲寬度是影響你UI設計的關鍵因素.UI在豎直方向上會經常滾動,但是在水平方向上往往是固定的佈局.可見不論是適配手機或者平板,寬度往往都是佈局的關鍵因素.因此,你需要關心你手機上的最小寬度值.
屏幕可用寬度 w<N>dp
Examples:
w720p
w1024p
指定資源使用時需要的最小寬度.當屏幕方向發生變化時,系統會調整這個值,使其始終爲你UI顯示的寬度.
這個屬性經常被用來判斷當前是否需要顯示多屏佈局,因爲哪怕用戶當前正在使用平板,你也可能不希望用戶在平板豎屏時顯示多個屏幕的佈局樣式.這時,你就可以使用這個限定符來標明你佈局需要的最小寬度
屏幕可用高度 h<N>dp
Examples:
h720dp
h1024dp
etc.
標明資源使用時需要的最小高度.當屏幕發生旋轉時,系統會自動選擇當前大的一方作爲高度值.大部分應用很少需要這個限定符,因此不做過多講解

While using these qualifiers might seem more complicated than using screen size groups, it should actually be simpler once you determine the requirements for your UI. When you design your UI, the main thing you probably care about is the actual size at which your application switches between a handset-style UI and a tablet-style UI that uses multiple panes. The exact point of this switch will depend on your particular design—maybe you need a 720dp width for your tablet layout, maybe 600dp is enough, or 480dp, or some number between these. Using these qualifiers in table 2, you are in control of the precise size at which your layout changes.

雖然看起來使用這些新的限定符會比使用廣義的屏幕尺寸組更加複雜,但是一旦你的UI需求確定之後,你會發現使用這些新的限定符會更加簡單.當你設計UI時,你關心的最主要的事情應該是應用程序在手機類型UI和多窗格平板類型的UI之間切換時的實際尺寸.切換的關鍵點在於特殊的設計,也許需要720dp寬度給平板佈局,也許600dp的寬度就夠了,或者480dp.使用新的限定符,你可以精確的掌握你佈局所需要的尺寸.

Configuration examples(配置示例)

To help you target some of your designs for different types of devices, here are some numbers for typical screen widths:

  • 320dp: a typical phone screen (240x320 ldpi, 320x480 mdpi, 480x800 hdpi, etc).
  • 480dp: a tweener tablet like the Streak (480x800 mdpi).
  • 600dp: a 7” tablet (600x1024 mdpi).
  • 720dp: a 10” tablet (720x1280 mdpi, 800x1280 mdpi, etc).

爲了幫助你實現爲不同類型設備設計UI的目標,下面是一些典型的屏幕寬度參數值:

  • 320dp: 典型的手機屏幕.
  • 480dp: 類似於手機的平板.
  • 600dp: 7寸的平板.
  • 720dp: 10寸的平板.

Using the size qualifiers from table 2, your application can switch between your different layout resources for handsets and tablets using any number you want for width and/or height. For example, if 600dp is the smallest available width supported by your tablet layout, you can provide these two sets of layouts:

res/layout/main_activity.xml # For handsets
res/layout-sw600dp/main_activity.xml # For tablets

In this case, the smallest width of the available screen space must be 600dp in order for the tablet layout to be applied.

使用表2中的限定符,可以讓你的應用在手機和平板上使用不同的佈局文件.例如,600dp是你平板佈局需要的最小寬度,你就可以提供如下兩個佈局文件:

res/ layout/main_activity.xml #爲手機佈局

在上面的佈局文件中,只有當屏幕可以寬度到達600dp時,layout-sw600dp目錄下的佈局文件纔會被使用.

For other cases in which you want to further customize your UI to differentiate between sizes such as 7” and 10” tablets, you can define additional smallest width layouts:

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)
res/layout-sw720dp/main_activity.xml # For 10” tablets (720dp wide and bigger)

再舉一個例子,如果你需要豐富你的UI佈局,例如爲7英寸和10英寸平板設計不同的佈局,你可以在如下不同的文件夾中定義同名的佈局文件:

res/layout/main_activity.xml #手機佈局
res/layout-sw600dp/main_activity.xml #7寸平板佈局
res/layout-sw720dp/main_activity.xml #10寸平板佈局

Notice that the previous two sets of example resources use the “smallest width” qualifier, sw<N>dp, which specifies the smallest of the screen’s two sides, regardless of the device’s current orientation. Thus, using sw<N>dp is a simple way to specify the overall screen size available for your layout by ignoring the screen’s orientation.

需要注意的是,前面的示例方案中都採用了sw<N>這種最小寬度標識的形式,這種形式可以讓開發者不去考慮當前屏幕的方向.所以在不考慮屏幕方向只關注佈局最小空間的前提下,使用sw<N>的方式更加簡單.

However, in some cases, what might be important for your layout is exactly how much width or height is currently available. For example, if you have a two-pane layout with two fragments side by side, you might want to use it whenever the screen provides at least 600dp of width, whether the device is in landscape or portrait orientation. In this case, your resources might look like this:

res/layout/main_activity.xml # For handsets (smaller than 600dp available width)
res/layout-w600dp/main_activity.xml # Multi-pane (any screen with 600dp available width or more)

然而,在某些情況下,你的佈局需要明確的知道當前寬和高的可用尺寸.例如,如果你有一個用兩個Fragment填充的兩個窗口的佈局文件,無論當時屏幕的方向如何,只要當屏幕的空間超過600dp時你就需要使用它,這種情況下,你就應該按照如下方式進行聲明:

res/layout/main_activity.xml # 手機佈局
res/layout-w600dp/main_activity.xml #平板佈局

Notice that the second set is using the “available width” qualifier, w<N>dp. This way, one device may actually use both layouts, depending on the orientation of the screen (if the available width is at least 600dp in one orientation and less than 600dp in the other orientation).

注意,上面的例子中使用的是可用寬度限定符w<N>dp.這種情況下,只要屏幕在橫向或縱向有一種情況下寬度達到600dp,就會使用這個layout-w600dp目錄下的佈局文件.

Declaring screen size support(AndroidManifest.xml中支持屏幕尺寸的聲明字段)

Once you’ve implemented your layouts for different screen sizes, it’s equally important that you declare in your manifest file which screens your application supports.

一旦已經實現了不同屏幕尺寸的佈局,那麼在AndroidManifest.xml文件中聲明應用程序應該支持哪種屏幕也非常重要.

Along with the new configuration qualifiers for screen size, Android 3.2 introduces new attributes for the <supports-screens> manifest element:

  • android:requiresSmallestWidthDp
    Specifies the minimum smallestWidth required. The smallestWidth is the shortest dimension of the screen space (in dp units) that must be available to your application UI—that is, the shortest of the available screen’s two dimensions. So, in order for a device to be considered compatible with your application, the device’s smallestWidth must be equal to or greater than this value. (Usually, the value you supply for this is the “smallest width” that your layout supports, regardless of the screen’s current orientation.)
    For example, if your application is only for tablet-style devices with a 600dp smallest available width:

    <manifest ... >
        <supports-screens android:requiresSmallestWidthDp="600" />
    </manifest>

    However, if your application supports all screen sizes supported by Android (as small as 426dp x 320dp), then you don’t need to declare this attribute, because the smallest width your application requires is the smallest possible on any device.

  • android:compatibleWidthLimitDp
    This attribute allows you to enable screen compatibility mode as a user-optional feature by specifying the maximum “smallest width” that your application supports. If the smallest side of a device’s available screen is greater than your value here, users can still install your application, but are offered to run it in screen compatibility mode. By default, screen compatibility mode is disabled and your layout is resized to fit the screen as usual, but a button is available in the system bar that allows users to toggle screen compatibility mode on and off.

  • android:largestWidthLimitDp
    This attribute allows you to force-enable screen compatibility mode by specifying the maximum “smallest width” that your application supports. If the smallest side of a device’s available screen is greater than your value here, the application runs in screen compatibility mode with no way for the user to disable it.

Android3.2隨着新的限定符也引進了新的manifest元素屬性:

  • 指定應用所需要的最小寬度.
    SmallestWidth必須是能被應用程序UI利用的屏幕控件的最小尺寸(單位是dp),也是屏幕高或寬中的最小尺寸.因此,爲了讓設備與應用程序兼容,設備的smallestWidth必須大於等於這個值.
    例如,如果你的應用只適配最小寬度爲600dp的屏幕,那需要在AndroidManifest中添加如下聲明:

    <manifest ... >
        <supports-screens android:requiresSmallestWidthDp="600" />
    </manifest>

    然而,如果應用程序支持所有Android支持的屏幕尺寸,那麼沒有必要申明這個屬性了.

  • android:compatibleWidthLimitDp
    這個屬性用來兼容通過指定應用程序支持的最小寬度.如果可用設備的最小值大於這個值,用戶仍然可以安裝應用程序,但是不能再屏幕的兼容模式上運行.默認情況下,屏幕的兼容模式是關閉的.

  • android:largestWidthLimitDp
    這個屬性通過指定你的應用程序支持的最大“最小寬度”強制開啓屏幕的兼容模式,如果設備的可用屏幕最小邊大於這個值,應用程序會運行在屏幕兼容模式上,且用戶沒有辦法去禁用它.


Best Practices(最佳實踐)

The objective of supporting multiple screens is to create an application that can function properly and look good on any of the generalized screen configurations supported by Android. The previous sections of this document provide information about how Android adapts your application to screen configurations and how you can customize the look of your application on different screen configurations. This section provides some additional tips and an overview of techniques that help ensure that your application scales properly for different screen configurations.

支持多個屏幕尺寸的目標是開發一個在任何屏幕尺寸上都能夠很好顯示的Android應用程序.本文前面的章節介紹了Android系統是如何讓應用程序適配不同屏幕的以及如何在不同尺寸的屏幕上自定義自己的UI佈局.這一章節提供了更多的適配多種屏幕的開發技巧.

Here is a quick checklist about how you can ensure that your application displays properly on different screens:

  1. Use wrap_content, match_parent, or dp units when specifying dimensions in an XML layout file
  2. Do not use hard coded pixel values in your application code
  3. Do not use AbsoluteLayout (it’s deprecated)
  4. Supply alternative bitmap drawables for different screen densities

The following sections provide more details.

這裏給出適配方案的簡介列表:

  1. 在layout佈局中聲明寬或高時儘量使用wrap_content, match_parent或者dp等密度無關的度量單位.
  2. 不要在應用程序代碼中爲佈局指定px硬編碼.
  3. 不要使用絕對佈局,AbsoluteLayout佈局已經被廢棄了.
  4. 爲不同密度的屏幕提供不同的圖片資源.

接下來,是每一條建議的詳細描述.

1. Use wrap_content, match_parent, or the dp unit for layout dimensions(儘量使用wrap_content, match_parent或者dp等密度無關度量標識符)

When defining the android:layout_width and android:layout_height for views in an XML layout file, using “wrap_content”, “match_parent” or dp units guarantees that the view is given an appropriate size on the current device screen.

在layout佈局文件中定義寬和高時,使用wrap_content, match_parent, dp等密度無關單位可以在不同的屏幕尺寸上都獲得比較好的顯示效果.

For instance, a view with a layout_width=”100dp” measures 100 pixels wide on medium-density screen and the system scales it up to 150 pixels wide on high-density screen, so that the view occupies approximately the same physical space on the screen.

例如,一個View的寬度聲明爲100dp,則意味着在mdpi的屏幕上,這個View佔據的寬度爲100px,而在hdpi的屏幕上,這個View佔據的寬度爲150px.因此雖然兩個屏幕的密度不同,但是View控件寬度所佔據的屏幕比例幾乎是相同的.

Similarly, you should prefer the sp (scale-independent pixel) to define text sizes. The sp scale factor depends on a user setting and the system scales the size the same as it does for dp.

同樣的,在修飾文字大小時建議使用sp爲單位,而不是使用px.sp針對字體大小的效果和dp針對view大小的效果類似.

2. Do not use hard-coded pixel values in your application code(不要在應用代碼中強制寫死px大小)

For performance reasons and to keep the code simpler, the Android system uses pixels as the standard unit for expressing dimension or coordinate values. That means that the dimensions of a view are always expressed in the code using pixels, but always based on the current screen density. For instance, if myView.getWidth() returns 10, the view is 10 pixels wide on the current screen, but on a device with a higher density screen, the value returned might be 15. If you use pixel values in your application code to work with bitmaps that are not pre-scaled for the current screen density, you might need to scale the pixel values that you use in your code to match the un-scaled bitmap source.

爲了性能考慮和兼顧代碼簡潔,Android系統使用px作爲尺寸和座標值的標準單位.這意味着,在代碼中去測量一個View的大小總是基於當前屏幕的密度轉換成px來表示.例如,通過myView.getWidth()返回的值爲10,說明在當前屏幕密度下myView佔據的寬度爲10px,但是當換一個更高密度的屏幕時,myView.getWidth()返回的值可能就是15px了.如果你基於當前屏幕密度下,使用px來測試bitmap的大小,你計算時需要考慮到當前的屏幕密度值.

3. Do not use AbsoluteLayout(不要使用絕對佈局)

Unlike the other layouts widgets, AbsoluteLayout enforces the use of fixed positions to lay out its child views, which can easily lead to user interfaces that do not work well on different displays. Because of this, AbsoluteLayout was deprecated in Android 1.5 (API Level 3).

不像其他佈局控件,AbsoluteLayout強制你在xml文件裏固定每個子View的位置,這很容易導致你的佈局文件不能適配其他密度的屏幕.因此,AbsoluteLayout在Android1.5上就被廢棄了.

You should instead use RelativeLayout, which uses relative positioning to lay out its child views. For instance, you can specify that a button widget should appear “to the right of” a text widget.

Android系統推薦你使用RelativeLayout,它可以讓你的子控件的佈局可以根據情況動態調整.例如,你可以讓一個Button佈局在一個TextView的右邊.

4. Use size and density-specific resources(使用限定符修飾的佈局和資源)

Although the system scales your layout and drawable resources based on the current screen configuration, you may want to make adjustments to the UI on different screen sizes and provide bitmap drawables that are optimized for different densities. This essentially reiterates the information from earlier in this document.

儘管Android系統會基於當前屏幕尺寸和密度來調整你的佈局和圖片資源,但是你可能希望在不同的屏幕尺寸和密度上顯示不同的資源圖片或者佈局.前文已經詳細介紹過這種實現方法了,就是通過限定符來標識目錄.

If you need to control exactly how your application will look on various screen configurations, adjust your layouts and bitmap drawables in configuration-specific resource directories. For example, consider an icon that you want to display on medium and high-density screens. Simply create your icon at two different sizes (for instance 100x100 for medium-density and 150x150 for high-density) and put the two variations in the appropriate directories, using the proper qualifiers:

res/drawable-mdpi/icon.png //for medium-density screens
res/drawable-hdpi/icon.png //for high-density screens

如果你需要能精確的控制你的應用在不同屏幕尺寸和密度下的顯示,你就需要用到限定符修飾的目錄.例如,你想要在mdpi和hdpi兩種屏幕密度下顯示不同的icon圖片,你可以先創建兩個不同尺寸的icon圖片,然後把它們分別放到被特定限制符修飾的目錄下(100x100大小的圖片放到mdpi目錄,150x150大小的圖片放到hdpi目錄下).


Additional Density Considerations(附加註意事項)

This section describes more about how Android performs scaling for bitmap drawables on different screen densities and how you can further control how bitmaps are drawn on different densities. The information in this section shouldn’t be important to most applications, unless you have encountered problems in your application when running on different screen densities or your application manipulates graphics.

這個章節會更加詳細的介紹Android系統是如何調整圖片資源的,同時介紹了更多方法讓你可以更好的操控圖片在不同密度屏幕上的顯示.

To better understand how you can support multiple densities when manipulating graphics at runtime, you should understand that the system helps ensure the proper scale for bitmaps in the following ways:

  • Pre-scaling of resources (such as bitmap drawables)
    Based on the density of the current screen, the system uses any size- or density-specific resources from your application and displays them without scaling. If resources are not available in the correct density, the system loads the default resources and scales them up or down as needed to match the current screen’s density. The system assumes that default resources (those from a directory without configuration qualifiers) are designed for the baseline screen density (mdpi), unless they are loaded from a density-specific resource directory. Pre-scaling is, thus, what the system does when resizing a bitmap to the appropriate size for the current screen density.
    If you request the dimensions of a pre-scaled resource, the system returns values representing the dimensions after scaling. For example, a bitmap designed at 50x50 pixels for an mdpi screen is scaled to 75x75 pixels on an hdpi screen (if there is no alternative resource for hdpi) and the system reports the size as such.
    There are some situations in which you might not want Android to pre-scale a resource. The easiest way to avoid pre-scaling is to put the resource in a resource directory with the nodpi configuration qualifier. For example:
    res/drawable-nodpi/icon.png
    When the system uses the icon.png bitmap from this folder, it does not scale it based on the current device density.

  • Auto-scaling of pixel dimensions and coordinates
    An application can disable pre-scaling by setting android:anyDensity to “false” in the manifest or programmatically for a Bitmap by setting inScaled to “false”. In this case, the system auto-scales any absolute pixel coordinates and pixel dimension values at draw time. It does this to ensure that pixel-defined screen elements are still displayed at approximately the same physical size as they would be at the baseline screen density (mdpi). The system handles this scaling transparently to the application and reports the scaled pixel dimensions to the application, rather than physical pixel dimensions.
    For instance, suppose a device has a WVGA high-density screen, which is 480x800 and about the same size as a traditional HVGA screen, but it’s running an application that has disabled pre-scaling. In this case, the system will “lie” to the application when it queries for screen dimensions, and report 320x533 (the approximate mdpi translation for the screen density). Then, when the application does drawing operations, such as invalidating the rectangle from (10,10) to (100, 100), the system transforms the coordinates by scaling them the appropriate amount, and actually invalidate the region (15,15) to (150, 150). This discrepancy may cause unexpected behavior if your application directly manipulates the scaled bitmap, but this is considered a reasonable trade-off to keep the performance of applications as good as possible. If you encounter this situation, read the following section about Converting dp units to pixel units.
    Usually, you should not disable pre-scaling. The best way to support multiple screens is to follow the basic techniques described above in How to Support Multiple Screens.

爲了更好的理解Android系統是如何在運行時對圖片資源進行調整,你需要理解Android系統是如何來選中合適的圖片資源的,以下是Android系統的篩選步驟:

  • 預先調整資源
    基於當前屏幕的密度,系統會選擇是否有匹配限定符修飾的資源.如果沒有匹配限定符修飾的資源,系統會使用默認的圖片資源並依據當前屏幕的密度進行適當調整.系統假定默認資源目錄(即沒有被限定符修飾的目錄)中的資源都是爲標準屏幕(即mdpi)準備的.
    如果開發人員需要知道被預先調整資源的大小,系統會返回已經按照當前屏幕密度調整後的圖片大小.例如,針對mdpi屏幕提供的50x50像素的圖片在hdpi屏幕上返回的大小是75x75像素.
    想讓Android不去調整你的資源有很多種方法,其中最簡單的就是將資源放到被nodpi限定符修飾的目錄中.例如:
    res/drawable-nodpi/icon.png
    當系統使用drawable-nodpi目錄下的icon.png圖片時,無論當前屏幕密度是多少,icon都不會被調整.

  • 自動調節尺寸和座標值
    應用可以通過在AndroidManifest.xml中設置android:anyDensity爲false或者在代碼中設置Bitmap的inScaled爲false來禁止預先的調整資源.在這種情況下,系統會在繪製時自動調整絕對像素的座標值和尺寸.這樣做的目的是,爲了確保已經定義像素的元素在其他密度的屏幕上仍然能夠以接近它們在基準屏幕密度上的比例顯示出來.系統會把調整後的像素值告知應用程序,調整過程對應用程序來說是透明的.
    例如,假定一個設備有WVGA高密度屏幕,即480x800,這與傳統的HVGA屏幕的尺寸大致相同,但是該設備已經禁止了預先調整應用資源的功能.在這種情況下,在應用程序查詢當前屏幕密度時,系統會欺騙應用程序,假定當前的屏幕密度爲320x533(欺騙的屏幕密度接近mdpi).然後,當應用程序開始繪製操作時,例如使(10,10)到(100, 100)的區域對應用無效,應用會將這部分座標值進行相應的調整,最終無效的區域實際是(15, 15)到(150, 150).如果你的應用程序直接使用調整後的Bitmap對象,這個誤差會導致不可預期的行爲,但是這被認爲是合理的折衷的儘可能保持應用性能的方法.
    通常情況下,你不應該禁止系統的預先調整功能.最好的適配多種屏幕密度的方式就是參考本文之前介紹的方法.

If your application manipulates bitmaps or directly interacts with pixels on the screen in some other way, you might need to take additional steps to support different screen densities. For example, if you respond to touch gestures by counting the number of pixels that a finger crosses, you need to use the appropriate density-independent pixel values, instead of actual pixels.

如果你的應用程序在屏幕上以其他某種方式操作Bitmap對象或者直接與像素交互,你可能需要採取額外的步驟來支持不同密度的屏幕.例如,你可以計算手指劃過的像素值來響應觸摸,你需要使用密度無關像素值,而不是使用實際的像素值.

Scaling Bitmap objects created at runtime(在運行時調整Bitmap對象)

If your application creates an in-memory bitmap (a Bitmap object), the system assumes that the bitmap is designed for the baseline medium-density screen, by default, and auto-scales the bitmap at draw time. The system applies “auto-scaling” to a Bitmap when the bitmap has unspecified density properties. If you don’t properly account for the current device’s screen density and specify the bitmap’s density properties, the auto-scaling can result in scaling artifacts the same as when you don’t provide alternative resources.

如果你的應用在內存中創建一個Bitmap對象,系統會認爲這個Bitmap對象是爲標準密度屏幕設計的,默認情況下,在繪製時會自動調整Bitmap對象.當Bitmap對象沒有明確定義自己的density屬性是,系統會採用自動調整的方式.如果你沒有考慮到當前屏幕密度也沒有聲明Bitmap的density屬性,系統會和沒有提供可選擇資源時的方式一樣去處理Bitmap對象.

To control whether a Bitmap created at runtime is scaled or not, you can specify the density of the bitmap with setDensity(), passing a density constant from DisplayMetrics, such as DENSITY_HIGH or DENSITY_LOW.

爲了控制在運行時是否對Bitmap對象進行調整,你可以通過setDensity()函數對Bitmap對象的density屬性進行指定.傳遞的參數應該是DisplayMetrics對象的常量,例如DENSITY_HIGH或者DENSITY_LOW.

If you’re creating a Bitmap using BitmapFactory, such as from a file or a stream, you can use BitmapFactory.Options to define properties of the bitmap as it already exists, which determine if or how the system will scale it. For example, you can use the inDensity field to define the density for which the bitmap is designed and the inScaled field to specify whether the bitmap should scale to match the current device’s screen density.

如果你使用BitmapFactory類從文件或者流中創建Bitmap對象,你可以使用BitmapFactory.Options來定義bitmap的屬性值.例如,你可以使用inDensity字段來定義Bitmap是爲哪種屏幕密度設計的,也可以使用inScaled字段來定義Bitmap在當前屏幕密度下是否需要系統進行調整.

If you set the inScaled field to false, then you disable any pre-scaling that the system may apply to the bitmap and the system will then auto-scale it at draw time. Using auto-scaling instead of pre-scaling can be more CPU expensive, but uses less memory.

如果你設置inScaled字段值爲false,相當於禁用了系統的Bitmap預先調整功能,系統會在運行時繪製Bitmap的時候對其自動進行調整.使用自動調整方案,會增加CPU的負擔,但同時也會減少內存的使用.

Figure 5 demonstrates the results of the pre-scale and auto-scale mechanisms when loading low (120), medium (160) and high (240) density bitmaps on a high-density screen. The differences are subtle, because all of the bitmaps are being scaled to match the current screen density, however the scaled bitmaps have slightly different appearances depending on whether they are pre-scaled or auto-scaled at draw time.

圖5展示了在hdpi屏幕密度上加載低(120),中(160)和高(240)密度圖片預先調整和自動調整的效果對比.區別是很微小的,因爲Bitmap對象都會調整成適應當前屏幕密度的樣式,然而在外觀上還是會有些許不同,這取決於是採用預先調整還是繪製時自動調整.

figure5

Converting dp units to pixel units(dp和px單位轉換)

In some cases, you will need to express dimensions in dp and then convert them to pixels. Imagine an application in which a scroll or fling gesture is recognized after the user’s finger has moved by at least 16 pixels. On a baseline screen, a user’s must move by 16 pixels / 160 dpi, which equals 1/10th of an inch (or 2.5 mm) before the gesture is recognized. On a device with a high-density display (240dpi), the user’s must move by 16 pixels / 240 dpi, which equals 1/15th of an inch (or 1.7 mm). The distance is much shorter and the application thus appears more sensitive to the user.

在某些情況下,你可能在xml文件中使用dp來標註大小同時需要在代碼中將其轉成px.在應用程序中,只有當用戶手指劃過16px時纔會被系統認爲是一個scroll或者fling的手勢.在標準密度的屏幕上,用戶必須移動 16px / 160dpi,相當於 1 / 10 英寸才能被檢測到.在高密度的屏幕上(240dpi),用戶必須移動16px/240dpi,相當於1/15英寸.這個距離在更高分辨率的屏幕上會顯得更加敏感.

To fix this issue, the gesture threshold must be expressed in code in dp and then converted to actual pixels. For example:

爲了解決這個問題,gesture threshold必須用dp來表示距離,並且在不同密度的屏幕上將其轉換成像素.例如:

// The gesture threshold expressed in dp
private static final float GESTURE_THRESHOLD_DP = 16.0f;

// Get the screen’s density scale
final float scale = getResources().getDisplayMetrics().density;
// Convert the dps to pixels, based on density scale
mGestureThreshold = (int) (GESTURE_THRESHOLD_DP * scale + 0.5f);

// Use mGestureThreshold as a distance in pixels...

How to Test Your Application on Multiple Screens(如何使用模擬器在不同密度屏幕上測試你的應用程序)

Before publishing your application, you should thoroughly test it in all of the supported screen sizes and densities. The Android SDK includes emulator skins you can use, which replicate the sizes and densities of common screen configurations on which your application is likely to run. You can also modify the default size, density, and resolution of the emulator skins to replicate the characteristics of any specific screen. Using the emulator skins and additional custom configurations allows you to test any possible screen configuration, so you don’t have to buy various devices just to test your application’s screen support.

在你發佈應用之前,你應該在所有你想支持的密度和尺寸的屏幕上測試你的應用程序.Android SDK中提供了模擬器來幫助你實現在不同屏幕尺寸和屏幕密度上測試你的應用.你可以修改模擬器的屏幕尺寸,屏幕密度和屏幕分辨率.使用模擬器可以幫你模擬任何你想模擬的屏幕,這樣你就不需要去購買真實設備來測試你的應用程序了.

To set up an environment for testing your application’s screen support, you should create a series of AVDs (Android Virtual Devices), using emulator skins and screen configurations that emulate the screen sizes and densities you want your application to support. To do so, you can use the AVD Manager to create the AVDs and launch them with a graphical interface.

爲了給你的應用搭建測試環境,你應該使用你想支持的屏幕尺寸和屏幕密度創建一系列Android虛擬設備.要做到這一點,可以使用AVD管理器去創建AVD,然後在圖形化界面啓動AVD.

To launch the Android SDK Manager, execute the SDK Manager.exe from your Android SDK directory (on Windows only) or execute android from the <sdk>/tools/ directory (on all platforms). Figure 6 shows the AVD Manager with a selection of AVDs, for testing various screen configurations.

爲了啓動Android SDK Manager,在window環境下可以在你Android SDK目錄下執行SDK Manager.exe文件,在其他環境下(Linux或者Mac),可以再SDK目錄的tools目錄下執行android這個應用程序.圖6展示了AVD Manager的示例.

figure6

Table 3 shows the various emulator skins that are available in the Android SDK, which you can use to emulate some of the most common screen configurations.

表三展示了Android SDK中你可以使用的通用模擬器屬性值.

table3

We also recommend that you test your application in an emulator that is set up to run at a physical size that closely matches an actual device. This makes it a lot easier to compare the results at various sizes and densities. To do so you need to know the approximate density, in dpi, of your computer monitor (for instance, a 30” Dell monitor has a density of about 96 dpi). When you launch an AVD from the AVD Manager, you can specify the screen size for the emulator and your monitor dpi in the Launch Options, as shown in figure 7.

我們同樣建議在屏幕尺寸大約接近的模擬器上測試應用程序.這樣做可以使得比較結果更加明顯.爲了做到這一點,你需要知道電腦顯示器的近似密度.當你從AVD Manager啓動AVD時,你可以指定模擬器的屏幕尺寸和顯示器的dpi如表7所示.

figure7

If you would like to test your application on a screen that uses a resolution or density not supported by the built-in skins, you can create an AVD that uses a custom resolution or density. When creating the AVD from the AVD Manager, specify the Resolution, instead of selecting a Built-in Skin.

如果你想在一個沒有在內置屬性支持的屏幕上測試應用程序,你可以創建一個使用自定義分辨率或者屏幕密度的AVD.在創建AVD時,應該手動的指定屏幕密度和分辨率.

If you are launching your AVD from the command line, you can specify the scale for the emulator with the -scale option. For example:

如果你從命令行啓動AVD,你可以通過-scale參數來指定屏幕分辨率.例如:

emulator -avd<avd_name> -scale 96dpi

To refine the size of the emulator, you can instead pass the -scale option a number between 0.1 and 3 that represents the desired scaling factor.

爲了改變模擬器的尺寸,你可以通過指定-scale參數的值爲0.1~3來改變比例因子.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章