Android如何支持多種屏幕

支持多屏

Android涉及各種各樣的支持不同屏幕尺寸和密度的設備。對於應用程序,Android系統通過設備和句柄提供了統一的開發環境,大部分工作是校正每一個應用程序的用戶界面到它顯示的屏上。與此同時,系統提供APIs允許你控制應用界面爲特定的屏幕尺寸和密度,爲不同屏幕的配置提供最優化的用戶界面設計。例如,你可能會要一個平板電腦的用戶界面,這不同於手機的用戶界面。

雖然系統能縮放,調整其尺寸,以使應用軟件工作在不同屏上,但是應該儘量優化應用軟件適應不同的屏幕尺寸和密度。爲此,對所有設備的用戶體驗應最大化且應讓用戶們相信應用軟件是真正爲他們的設備設計的,而不是簡單的拉伸使屏適合他們的設備。

按照文中描述的做法,通過使用一個apk文件,可以創建一個應用軟件能恰當顯示並在所有的支持屏配置中提供最優用戶體驗。

多屏支持概述

本節提供了Android支持多屏的概述,包括:介紹了本文中API用到的術語和概念,總結了系統支持的屏設置,概述了API和下面的屏幕兼容特性。

術語和概念

屏幕尺寸

實際的物理尺寸,是按照屏幕的對角線計量的。www.saige.com/shop/auction-27230.htm
爲簡單起見,Android把所有的屏幕尺寸劃分爲四種廣義的尺寸:小、標準、大,特大號。

屏幕密度

屏幕佔據的物理區域所含像素的個數;通常被稱爲dpi(每英寸點數).
例如在給定的物理區域中,與“標準的”或“高”密度屏幕相比,低密度屏幕具有較少的像素。

方向

屏幕的方向來自於用戶的角度。這是橫向或縱向,分別指屏幕各個角度的比例,而不是寬或高。需要注意的是,不僅不同的設備在不同方向運行,而且當用戶旋轉設備時,方向也同時在改變。

分辨率

屏幕上物理像素的總數。支持多屏時,應用程序不直接與分辨率有關,應用程序應該只關心屏幕的尺寸和密度,用指定的廣義的尺寸和密度組。

dp

一種有效的在定義UI佈局時你應當使用的像素單位,以一種密度無關的方式表示佈局的尺寸或者位置。
dp相當於160dpi屏幕,它是系統爲“中等的”密度屏設定的基準密度。同時,系統透明地處理任何一種dp單位,必要時,基於使用中的屏的實際密度。dp單位根據公式 px = dp * (dpi / 160)簡單地轉化爲屏像素。例如,一個240dpi的屏幕,1 dp等於1.5個物理像素。定義應用程序的UI時,你應該總是使用dp單位,以確保在不同密度的屏幕上正確地顯示你的UI。

支持的屏幕範圍

從Android1.6(API等級爲4)開始,Android提供了支持多個屏幕的尺寸和密度,表明一種設備擁有許多不同的屏幕配置。你應該利用Android系統的這些特性去爲每一個屏幕配置優化你的應用程序界面,並且應確保你的應用程序不僅能正常運行,而且應儘可能地在每一個屏幕上提供最好的用戶體驗。

爲了簡化爲多個屏的用戶界面設計方式,Android系統將實際的屏幕尺寸和密度範圍劃分爲:

  • 一組廣義的尺寸:小,標準,大,特大號。

:從Android3.2(API等級爲13)起,這些尺寸分組已被棄用,大家支持的是一種新的基於可用屏幕寬度的管理屏幕尺寸的技術。如果你正在開發Android3.2或者更高版本,參見Android3.2平板電腦佈局章節獲取更多信息。

  • 一組四個廣義的密度:ldpi (低), mdpi (中等), hdpi (高),和 xhdpi (超高)。

這種廣義的尺寸和密度是圍繞一種基準的配置進行劃分的,這種基準的配置是指一個標準尺寸和mdpi (中等)密度。這個基線是基於第一個Android 上電設備,T-Mobile G1的屏幕配置,它具有HVGA屏幕(直到Android1.6,這是Android支持的唯一的屏幕配置)。

每個廣義的尺寸和密度跨越一套實際屏幕尺寸和密度。例如,當用手測量時,兩種標準的屏幕尺寸的設備可能具有實際的稍微不同的屏幕尺寸和縱橫比。同樣,兩種hdpi屏幕密度的設備可能包含稍微不同的實際像素密度。Android製造這些差異使應用程序抽象化,所以,你可以提供設計的UI給廣義的尺寸和密度,必要時讓系統處理任何最後的調整。圖1 闡明瞭不同的尺寸和密度被如何大致歸類到不同的尺寸和密度組。

screens-ranges.png

圖1 闡明瞭不同的尺寸和密度被如何大致歸類到不同的尺寸和密度組

當爲不同的屏幕尺寸設計UI時,會發現每個設計需要最低限度的空間。因此,上面提到的每一個廣義的屏幕尺寸都有系統定義的相關聯的最小分辨率。這些最小尺寸在“dp”單位內,當設計佈局時,應當使用相同的單位。

  • 超大屏幕至少960dp x720dp
  • 大屏幕至少640dp x480dp
  • 標準屏幕至少470dp x320dp
  • 小屏幕至少426dp x320dp

:在Android3.0之前,這些最小屏幕尺寸沒有很好的定義,所以可能會遇到一些在標準和大之間被錯誤歸類的設備。這些也是基於屏幕的物理分辨率,因此各種不相同的設備也會遇到前面的問題。例如,一個有系統欄的1024x720平板會留少一點可用的空間給應用程序。

爲了優化應用程序的UI適應不同的屏幕尺寸和密度,可以提供任何廣義的尺寸和密度替代資源。一般來說,應當提供替代佈局給不同屏幕尺寸和替代的位圖圖像給不同的屏幕密度。在運行時,基於當前設備屏幕的廣義的尺寸或密度,系統會爲你的應用程序使用適當的資源。

沒有必要提供替代資源給每個屏幕尺寸和密度的組合。系統提供了強大的兼容特性,這些特性會處理大部分工作使你的應用程序呈現在任何設備的屏幕上,前提是已經通過使用允許它適當地調整尺寸的技術實現了UI(正如下面最佳實踐中描述的)。

:定義一種設備的廣義的屏幕尺寸和密度特性是彼此相互獨立的。例如,一種WVGA高密度屏幕被認爲是標準尺寸的屏幕,是因爲它的物理大小與T-Mobile G1(Android的第一個設備和基準屏幕設置)大約相同。另一方面,一種 WVGA中等密度的屏幕被認爲是大尺寸的屏幕。儘管它有相同的分辨率(相同數量的像素),這種WVGA中等密度的屏幕有更低的屏幕密度,意思是每個像素比較大,因此,整個屏幕比基準(標準尺寸)屏幕要更大。

密度無關性

當應用程序保留了用戶界面元素的物理尺寸以不同的密度顯示在屏幕上(從用戶的角度來看)時,它實現了“密度無關性”。 維護密度無關係性很重要,因爲,如果沒有它,一個UI元素(如按鈕)在一個低密度屏幕上看起來較大而在一個高密度屏幕上看起來很小。這樣的密度相關的尺寸的改變影響應用程序的佈局和使用。圖2和圖3 分別展示了當它不提供密度無關性和提供了密度無關性時,應用程序之間的差異。

density-test-bad.png

圖2 當不提供密度無關性,應用程序在低、中等、高密度屏幕上顯示實例

density-test-good.png

圖3 當提供密度無關性,應用程序在低、中等、高密度屏幕上顯示實例

Android系統通過以下兩種方式幫助應用程序實現密度無關性:

  • 系統爲當前屏幕密度調整dp單位到適當的值
  • 如有必要,系統會根據當前屏幕密度調整繪圖資源到適當的尺寸

在圖2中,文本視圖和位圖繪圖有規定的尺寸的像素(像素單位),因此這些視圖在低密度屏幕上看起來較大,在高密度屏幕上看起來較小。這是因爲儘管實際的屏幕尺寸是一樣的,但是高密度屏每英尺有較多的像素(相同數量的像素適合於較小區域)。在圖3中,佈局的尺寸被指定爲密度無關性像素(dp 單位)。因爲密度無關性像素的基線是中等密度的屏幕,一個有中等密度屏幕的設備看上去與圖2中的一樣。對於低密度和高密度屏幕而言,不管怎樣,系統能分別降低、調高密度無關性像素的值去恰當地適應屏幕。 在大多數情況下,你可以簡單地在密度無關性像素裏(dp 單位)指定所有的佈局尺寸或者恰當地“包裝內容”來確保應用程序的密度無關性。然後系統會根據恰當的縮放因子爲當前屏幕密度調整位圖視圖以適當的尺寸顯示出來。 但是,位圖縮放會導致圖片模糊,如上面的截圖。爲了避免這些問題,應該爲不同的密度提供替代位圖資源。例如,應該給高密度屏幕提供更高分辨率的位圖,系統會使用它們,而不是使用爲中等密度屏幕設計的縮放位圖。以下段落將介紹更多關於如何提供不同替代資源給不同的屏幕配置。

如何支持多屏

Android支持多屏的基礎是它能夠以適當的方式爲當前屏幕設置管理應用程序的佈局和位圖繪圖的渲染。根據實際情況,系統通過縮放佈局去適應屏幕的尺寸/密度和爲屏幕密度縮放位圖繪圖,處理大部分工作去適當地渲染應用程序到每一個屏幕配置。然而,爲了更好地處理不同屏幕配置,應該: *在清單文件中明確申明應用程序支持哪種屏幕大小

通過申明應用程序支持哪種屏幕尺寸,可以確保只有支持的屏幕尺寸的設備才能下載應用程序。聲明支持不同屏幕尺寸也會影響系統如何在較大屏幕上運行應用程序,尤其是,不論應用程序是否運行在屏幕兼容模式。 爲了申明應用程序支持的屏幕大小,應該在manifest文件中包含<supports-screens>的元素。

*爲不同的屏幕尺寸提供不同的佈局

默認情況下,Android會重新調整應用佈局去適合當前設備屏幕。在大多數情況下,這樣做很好。在其它情況下,UI可能看上去不太好且可能不同屏幕尺寸需要調整。例如,在較大屏幕上,可能會調整某些元素的位置和尺寸去充分利用額外的屏幕空間,或者在一個較小屏幕上,會調整尺寸使得一切都可以在屏幕上顯示。 可以提供指定大小資源的配置限定符,有小、標準、大、超大。例如,一個超大屏幕的佈局應該選Xlarge。 從Android3.2(API等級爲13)起,上面的尺寸分組已被棄用,你應該使用sw<N>dp配置限定符去定義佈局資源需要的最小的可用的寬度。例如,如果多窗格平板佈局需要至少600dp的屏幕寬度,應該選sw600dp。使用新技術申明佈局資源將會在Declaring Tablet Layouts for Android 3.2章節討論。

*爲不同的屏幕密度提供不同的位圖繪圖

默認情況下,Android調整你的位圖繪圖(.png, .jpg, and .gif 文件)和9補丁繪圖(.9.png 文件),讓他們在每個設備上以適當的物理尺寸呈現。例如,你用程序只爲基線、中等屏幕密度(mdpi)提供了位圖繪圖,系統會調高高密度屏幕,降低低密度屏幕。這些調整會導致圖片不真實。爲了確保圖片看起來最好,應當在不同分辨率下包含替代版本去適應不同的屏幕密度。可以用來指定密度資源的配置限定符有ldpi(低)、mdpi (中等), hdpi (高), and xhdpi (超高)。例如,高密度屏幕的位圖應該選hdpi。 尺寸和密度配置限定符與上面的支持的屏幕範圍中描述的廣義尺寸和密度一致。

註釋:如果你不太熟悉配置限定符且不知道系統如何使用他們應用替代資源的話,請閱讀Providing Alternative Resources章節獲取更多信息。 在運行時,對於任何給定的資源,系統通過以下步驟實現在當前屏幕上獲取最佳的顯示:

1.系統使用適當的替代資源

基於當前屏幕的尺寸和密度,系統會使用應用程序裏的任何指定尺寸和密度的資源。例如,如果設備有一個高密度屏幕且應用程序請求繪圖資源時,,系統會在繪圖資源目錄尋找最匹配的設備配置。依賴於其他可用的替代資源,一個有hdpi限定符的資源目錄(如 drawable-hdpi)可能是最匹配的,因此係統使用這個目錄中的繪圖資源。

2.如果沒有匹配的資源可用,系統會使用默認資源且會調高或降低資源去匹配當前屏幕的尺寸和密度這些“默認”資源是指那些沒有配置限定符標記的資源。例如在drawable/中的資源就是默認的繪圖資源。系統假定默認資源是爲基準屏幕尺寸和密度設計的,即標準屏幕尺寸和中等密度。例如,系統會恰當地爲高密度屏幕調高默認密度資源,爲低密度屏幕降低默認資源。

然而,當系統在尋找一個指定密度的資源且在指定密度目錄沒找到它時,它不會總是使用默認資源。爲了獲取更好的效果,系統會使用一個其他指定密度資源。例如,當系統在尋找一個低密度資源且這個資源是不可用時,系統更喜歡降低高密度版本的資源,因爲系統可以簡單地乘以0.5係數將高密度資源降低爲低密度,與調整中等密度資源乘以0.75係數相比,這樣用到很少的工件。

關於Android是如何通過匹配配置限定符到設備配置來選擇替代資源的更多信息,請閱讀How Android Finds the Best-matching Resource章節。

使用配置限定符

Android支持多種配置限定符,讓你控制系統如何基於當前設備屏幕的特徵選擇替代資源。一個配置限定符是一個字符串,你可以把它附加到你的Android工程的資源目錄中並指定裏面的資源是爲此配置設計的。

爲了使用配置限定符:

1.在你的工程的res目錄創建一個新目錄,並使用格式命名:

<resources_name>-<qualifier>
<resources_name>是標準的資源名稱(如drawable or layout)。
<qualifier>是下面表1中的配置限定符,指定這些資源將要被用的屏幕配置(如hdpi or xlarge)。

2.保存這些適當的指定配置的資源到這個新目錄。這些資源文件的命名必須嚴格與默認的資源文件名一樣.

例如,xlarge是用於超大屏幕的配置限定符。當你添加這些字符串到一個資源目錄名(如layout-xlarge)時,它告訴系統這些資源將被用到有超大屏幕的設備上。

表1 允許你提供指定資源給不同屏幕配置的配置限定符

Screen characteristic Qualifier Description

Size

small

Resources for small size screens

 

normal

Resources for normal size screens. (This is the baseline size.)

 

large

Resources for large size screens.

 

xlarge

Resources for extra large size screens

Density

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).

 

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.

Orientation

land

Resources for screens in the landscape orientation (wide aspect ratio).

 

port

Resources for screens in the portrait orientation (tall aspect ratio).

Aspect ratio

long

Resources for screens that have a significantly taller or wider aspect ratio (when in portrait or landscape orientation, respectively) than the baseline screen configuration.

 

notlong

Resources for use screens that have an aspect ratio that is similar to the baseline screen configuration.

注:如果在Android3.2或者更高版本上開發應用程序,請參閱Declaring Tablet Layouts for Android 3.2章節獲取關於新的配置限定符的信息,當申明瞭指定屏幕尺寸(而不是使用表1中的尺寸限定符的佈局資源時,你應當使用這些限定符。

獲取更多關於這些限定符如何大致對應於真實的屏幕尺寸和密度的信息,請參閱本文中前面提到的支持的屏幕範圍章節。

例如,下面是應用程序中的資源目錄列表,這個程序爲中等、高及超高密度屏幕提供了不同的爲不同屏幕尺寸和位圖繪圖設計的佈局。 res/layout/my_layout.xml // 標準屏幕尺寸的佈局("默認") res/layout-small/my_layout.xml // 小屏幕尺寸的佈局 res/layout-large/my_layout.xml // 大屏幕尺寸的佈局 res/layout-xlarge/my_layout.xml //超大屏幕尺寸的佈局 res/layout-xlarge-land/my_layout.xml // 橫向超大的屏幕布局

res/drawable-mdpi/my_icon.png // 中等密度的位圖 res/drawable-hdpi/my_icon.png //高密度的位圖 res/drawable-xhdpi/my_icon.png // 超高密度的位圖

如需要更多關於如何使用替代資源和完整的配置限定符列表(不僅僅是屏幕配置)的信息,請參閱Providing Alternative Resources。

請注意,當Android系統挑選資源時,它採用一定的邏輯來判定“最匹配”資源。也就是說,使用的限定符沒必要在所有情況下,爲了系統能用到它而嚴格匹配當前屏幕配置。具體來說,當基於尺寸的限定符選擇資源時,如果沒有更匹配的資源,系統會使用比當前屏幕更小的屏幕資源(例如,必要時,大尺寸屏幕將會使用標準尺寸屏幕資源)。但是,如果唯一可用的屏幕資源比當前屏幕大,系統將不會使用它們,而且如果沒有其他匹配設備的配置的話,應用程序將會崩潰(例如,如果所有佈局資源都被標記爲xlarger限定符,但是設備是一個標準尺寸的屏幕)。更多關於系統如何選擇資源的信息,請閱讀How Android Finds the Best-matching Resource章節。

小提示:如果你有一些系統從未調整過的繪圖資源(或許因爲在運行時對其進行了調整),應當把他們放置在nodpi配置個限定符的目錄。有這些限定符的資源被認爲是密度不可知的資源,系統將不會調整它們。

設計可替代的佈局和繪圖

應該創建的可替代資源的類型取決於應用程序的需要。通常,應該使用尺寸和方向限定符提供可替代的佈局資源,使用密度限定符去提供替代的位圖繪圖資源。 下面的段落分別總結了應該如何使用尺寸和密度限定符來提供替代的佈局和繪圖。

可替代的佈局

一般情況下,一旦在不同屏幕配置上測試應用程序,應該知道是否需要爲不同屏幕尺寸創建可替代的佈局。例如:

  • 當在小屏幕上測試時,可能會發現,佈局不是很適合這個屏幕。例如,一排按鈕可能不適合在小屏幕的設備的屏幕寬度內。這種情況下,應該爲小屏幕提供一種可替代的佈局,即通過調整這些按鈕的大小或位置。
  • 當在超大屏幕上測試時,可能會意識到,佈局並沒有有效地利用大屏幕,而是通過拉伸來填充它。在這種情況下,應該爲超大屏幕提供一種可替代的佈局,即可通過提供一種重新設計的最合適於較大屏幕如平板的UI。

雖然應用程序應當可以在沒有可替代佈局的大屏幕上工作正常,但是,對用戶來說,程序看起來好像是專門爲他們的設備設計的這一點非常重要。如果是很明顯被拉伸的UI,用戶對應用程序體驗會更加不滿意。

  • 而且,當在橫向測試時可能會注意到,與縱向相比較,放置在縱向屏幕底部的UI元素應該是在橫向屏幕的右側。


簡而言之,應該確保應用程序的佈局:

  • 適合在小屏幕上(這樣用戶真正使用應用程序)
  • 優化大屏幕,充分利用額外的屏幕空間
  • 優化橫向和縱向兩個方向


如果在系統調整了佈局後,UI要使用合適大小的位圖(如按鈕的背景圖片),應當使用九補丁的位圖文件。九補丁文件基本是一個指定的可拉伸的二維PNG文件。當系統需要調整正在使用的位圖的視圖時,系統會拉伸九補丁位圖,但僅延伸指定區域。同樣地,沒有必要提供不同的繪圖給不同的屏幕尺寸,因爲九補丁位圖能調整任何大小。然而,應當提供可替代的九補丁文件的版本給不同屏幕密度。

可替代的繪圖

幾乎每個應用程序應該有對應於不同屏幕密度的可替代的繪圖資源,因爲幾乎每個應用程序都有一個啓動圖標,而且圖標應該在所有屏幕密度上看起來都很好。同樣,如果在應用程序中包含了其他位圖繪圖(如菜單圖標或應用程序的其他圖像),應當提供可替代的版本或者每一個版本給不同的密度。

注:只需要給位圖文件((.png, .jpg, or .gif)和九補丁文件(.9.png)提供指定密度的繪圖。如果你使用XML去定義形狀,顏色或者其他繪圖資源,應該在默認的繪圖目錄(drawable/)做一個備份。

screens-densities.png

圖4支持每個密度的位圖繪圖的相對尺寸

爲了給不同密度創建可替代的位圖繪圖,應該遵循基於四種廣義密度的3:4:6:8的縮放比例。例如,你有一個48x48像素的中等密度屏幕的位圖繪圖(一個啓動圖標的尺寸),所有不同的尺寸應該是:

  • 36x36適合於低密度
  • 48x48適合於中等密度
  • 72x72適合於高密度
  • 96x96適合於超高密度

獲取更多關於設計圖標的信息,請參閱the Icon Design Guidelines,文中包含了各種位圖繪圖的尺寸信息,如啓動圖標,菜單圖標,狀態欄圖標,選項卡圖標等等。

Android3.2平板佈局的聲明

對於第一代運行在Android3.0上的平板,正確聲明平板佈局的方法是把他們放到一個有xlarge配置限定符的目錄裏(例如,res/layout-xlarge/)。爲了適應其他類型的平板和屏幕尺寸-尤其是7寸平板-Android3.2爲更多離散的屏幕尺寸引進了一種新的指定資源的方式。這項新技術是基於你的佈局需要的空間(如600dp的寬度),而不是試圖讓你的佈局去適合廣義的尺寸組(如large or xlarge)。

設計7寸平板的原因是非常複雜的,當時使用廣義的尺寸組是指一個7寸的平板在技術上與一個5寸的手機在同一個組(大組)。雖然這兩個設備在尺寸上看上去很接近,但是應用程序的UI的空間是顯著不同的,用戶交互的風格也是如此。因此,一個7寸和5寸的屏不應該總是使用同一個佈局。爲了把提供兩種不同屏的佈局變成可能,Android現在允許你基於寬度與/或者高度指定佈局資源,在dp單位中指定,這對於應用程序佈局很有效。

例如,在已經設計好了要用於平板類型的設備的佈局後,當屏幕少於600dp寬時,可能會決定讓佈局停止工作。這個閾值因此會成爲平板佈局需要的最小尺寸。照此,現在會指定這些佈局資源應當能被使用,僅僅在應用程序的UI有至少600dp寬度可用時。

應該要麼選擇寬度,並把它設計爲最小尺寸,要麼測試佈局一旦完成時,它支持的最小寬度是多少。

注:請記住,所有的這些新尺寸的APPs使用的數字都是密度無關性像素(dp)值,且佈局的維度應該總是被定義使用dp單位,因爲關心的是,系統佔用屏幕密度後可用屏幕空間的數量。更多關於密度無關性像素的信息,請閱讀文中前面提到的Terms and concepts。

新的尺寸限定符的使用

不同能夠指定的基於佈局的可用空間的資源配置的總結見表2。與傳統的屏幕尺寸組(小、標準、大和超大)相比,這些新的限定符提供了更多的控制權在指定的應用程序支持的屏幕尺寸方面。

注:指定的使用這些限定符的尺寸不是實際的屏幕尺寸。相反,在dp單位中的寬度或高度的尺寸對你的activity的窗口是可用的。Android系統可能會使用一些屏幕做系統UI(如屏幕底部的系統欄或頂部的狀態欄),所以一些屏幕有可能對於你的佈局是不可用的。因此,你申明的尺寸應該是,特別是你的activity需要的尺寸-當申明瞭系統能提供給你的佈局多少空間時,系統會佔用任何被系統UI使用的空間。還需要注意的是,工具欄被認爲是應用程序窗口空間的一部分,儘管你的佈局沒有申明,因此,系統會給佈局縮減可用空間,在設計時必須考慮到這點。

表2 屏幕尺寸的新配置限定符(Android 3.2中介紹的)

Screen configuratione Qualifier values Description

smallestWidth

sw<N>dp

Examples: sw600dp sw720dp

The fundamental size of a screen, as indicated by the shortest dimension of the available screen area. Specifically, the device's smallestWidth is the shortest of the screen's available height and width (you may also think of it as the "smallest possible width" for the screen). You can use this qualifier to ensure that, regardless of the screen's current orientation, your application's has at least <N> dps of width available for it UI.

For example, if your layout requires that its smallest dimension of screen area be at least 600 dp at all times, then you can use this qualifer to create the layout resources, res/layout-sw600dp/. The system will use these resources only when the smallest dimension of available screen is at least 600dp, regardless of whether the 600dp side is the user-perceived height or width. The smallestWidth is a fixed screen size characteristic of the device; the device's smallestWidth does not change when the screen's orientation changes.

The smallestWidth of a device takes into account screen decorations and system UI. For example, if the device has some persistent UI elements on the screen that account for space along the axis of the smallestWidth, the system declares the smallestWidth to be smaller than the actual screen size, because those are screen pixels not available for your UI.

This is an alternative to the generalized screen size qualifiers (small, normal, large, xlarge) that allows you to define a discrete number for the effective size available for your UI. Using smallestWidth to determine the general screen size is useful because width is often the driving factor in designing a layout. A UI will often scroll vertically, but have fairly hard constraints on the minimum space it needs horizontally. The available width is also the key factor in determining whether to use a one-pane layout for handsets or multi-pane layout for tablets. Thus, you likely care most about what the smallest possible width will be on each device.

Available screen width

w<N>dp

Examples: w720dp w1024dp

Specifies a minimum available width in dp units at which the resources should be used—defined by the <N> value. The system's corresponding value for the width changes when the screen's orientation switches between landscape and portrait to reflect the current actual width that's available for your UI.

This is often useful to determine whether to use a multi-pane layout, because even on a tablet device, you often won't want the same multi-pane layout for portrait orientation as you do for landscape. Thus, you can use this to specify the minimum width required for the layout, instead of using both the screen size and orientation qualifiers together.

Available screen height

h<N>dp

Examples: h720dp h1024dp etc.

Specifies a minimum screen height in dp units at which the resources should be used—defined by the <N> value. The system's corresponding value for the height changes when the screen's orientation switches between landscape and portrait to reflect the current actual height that's available for your UI.

Using this to define the height required by your layout is useful in the same way as w<N>dp is for defining the required width, instead of using both the screen size and orientation qualifiers. However, most apps won't need this qualifier, considering that UIs often scroll vertically and are thus more flexible with how much height is available, whereas the width is more rigid.

雖然使用這些限定符看上去比使用屏幕尺寸組更加複雜,但是當你一旦確定UI的需求後,這實際上應當更簡單。當設計UI時,可能關心的主要事情是,應用程序在手機類型的UI和多窗格的平板類型的UI之間切換時的實際尺寸。切換的關鍵在於特定的設計,也許需要720dp的寬度給平板佈局,也許600dp已足夠,或者480dp,或者其他位於這之間的數值。使用表2中的限定符,需要掌握佈局改變時的精確尺寸。

更多關於這些尺寸配置限定符的討論,請參閱Providing Resources文檔。

配置實例

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

  • 320dp:一種典型的手機屏幕 (240x320 ldpi, 320x480 mdpi, 480x800 hdpi, 等等).
  • 480dp: 一種有點像條紋的中間態的平板 (480x800 mdpi).
  • 600dp: 7寸平板 (600x1024 mdpi).
  • 720dp: 10寸平板 (720x1280 mdpi, 800x1280 mdpi, etc).

使用表2中的這些尺寸限定符,應用程序可以在使用任何想要的寬度或高度的平板和手機的不同佈局資源間切換。例如,如果平板佈局支持的最小可用寬度是600dp,應該提高兩套佈局:


res/layout/main_activity.xml # 手機適用

res/layout-sw600dp/main_activity.xml #平板適用


在這種情況下,爲了使平板佈局能用,可用的屏幕空間的最小寬度必須是600dp。

對於其他情況,你要進一步自定義你的UI以區分如7寸和10寸平板的尺寸,可以定義額外的最小寬度佈局:


res/layout/main_activity.xml # 適用於手機 (小於600dp的可用寬度)

res/layout-sw600dp/main_activity.xml #適用於7寸平板(大於等於600dp的可用寬度)

res/layout-sw720dp/main_activity.xml # 適用於10寸平板(大於或等於720dp的可用寬度)


請注意,第二套採用的“可用的寬度”限定符w<N>dp。通過這種方式,一個設備可能實際上使用兩種佈局,這取決於屏幕的方向(如果在一個方向上可用的寬度是至少600dp,在另一個方向上少於600dp)。

如果關心的是可用高度,可以同樣使用h<N>dp限定符。或者,如果情況比較特殊,甚至可以結合w<N>dp 和 h<N>dp一起使用。

支持屏幕尺寸的聲明

一旦已經實現了不同屏幕尺寸的佈局,在manifest文件中聲明應用程序支持哪種屏幕也同樣重要。

隨同新的屏幕尺寸的配置限定符一起,Android3.2引進了新的<supports-screens> manifest元素屬性。

android:requiresSmallestWidthDp

指定需要的最小smallestWidth。smallestWidth是必須能被應用程序的UI利用的屏幕空間的(在dp單位裏)最小尺寸。也就是,最短的可用的屏幕的二維尺寸。因此,爲了讓設備與應用程序兼容,設備的smallestWidth必須大於等於這個值。(通常,不論屏幕當前的方向是什麼,你提供的值是你的佈局支持的“最小寬度”。
例如,如果應用程序是爲600dp的最小可用寬度的平板類型設備設計的:
<manifest ... >
    <supports-screens android:requiresSmallestWidthDp="600" />
    ...
</manifest>
然而,如果應用程序支持所有Android支持的屏幕尺寸(如426dp x 320dp一樣小),那麼沒有必要申明這個屬性,因爲需要的最小寬度可能在任何設備上都是最小的。

注意:Android並不關心這個屬性,因此它不會影響應用程序在運行時的行爲。相反,它常常會爲應用程序在服務如谷歌播放上進行過濾。然而,谷歌播放目前不支持過濾屬性(在Android3.2上),因此,如果應用程序不支持小屏幕,應該繼續使用其它尺寸的屬性。

android:compatibleWidthLimitDp

這個屬性允許通過指定應用程序支持的最大“最小寬度”將屏幕的兼容模式作爲一個用戶可選特徵。如果設備的可用屏幕最小邊大於這個值,用戶仍然可以安裝應用程序,但是不能在屏幕的兼容模式上運行。默認情況下,屏幕的兼容模式是禁用的,和平常一樣,佈局會被調整到適合屏幕,但是按鈕在系統欄是可用的,它允許用戶開啓和關閉屏幕的兼容模式。

注:如果應用程序的佈局正好適合大屏幕,就沒必要使用這個屬性。我們建議避免使用這個屬性,而不是按照本文檔中的建議確保佈局適合更大屏幕。

android:largestWidthLimitDp

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

注:如果應用程序的佈局正好適合大屏幕,就沒必要使用這個屬性。我們建議避免使用這個屬性,而不是按照本文檔中的建議確保你的佈局適合更大屏幕。

注意:當在Android3.2或者更高版本上開發時,不應該使用較舊的屏幕尺寸屬性並結合上面列出的屬性。同時使用新屬性和較舊的尺寸屬性會導致不可預料的事情發生。

更多關於這些屬性的信息,請查閱以上相應的鏈接。

最佳實踐

支持多個屏幕的目的是爲了創建一個能正常運行,且在任何Android支持的廣義的屏幕配置上看起來都很舒服的應用程序。本文的前面章節提供了關於Android如何使應用程序適應屏幕配置和如何在不同屏幕配置上自定義應用程序的外觀的信息。這節提供了一些額外的技巧來確保應用程序適用於不同屏幕配置的技術。

下面是關於如何確保你的應用程序能夠恰當地顯示在不同屏幕上的快速檢查清單:

1.當在XML佈局文件中指定尺寸時,使用wrap_content, fill_parent, 或者dp單位

2.在應用程序代碼中不要使用硬編碼的像素值

3.不要使用絕對佈局(已被棄用)

4.對不同的屏幕密度採用可替代的位圖繪圖

下面章節將講述更多細節。

1.佈局尺寸使用wrap_content, fill_parent, 或者 dp單位

當在XML佈局文件中定義視圖的android:layout_width和 android:layout_height時,使用wrap_content, fill_parent, 或者 dp單位以保證在當前設備屏幕上能給視圖分配一個適當的尺寸。

例如,一個layout_width爲100dp的視圖在中等密度的屏幕上是100像素,在高密度屏幕上系統將把它調整到150dp,於是視圖在屏幕上佔用了大致相同的物理空間。

同樣地,應該更喜歡用sp(與比例無關的像素)來定義文本的尺寸。Sp比例因子取決於用戶的設置和系統調整的尺寸與它爲dp調整的相同。

2.在應用程序代碼中不要使用硬編碼的像素值

出於性能方面的原因及爲了保持代碼更簡單,Android系統採用像素作爲尺寸或座標值的標準單位。意思是,在代碼中,視圖的尺寸總是用像素表達,但總基於當前屏幕密度。例如,如果myView.getWidth()函數的返回值是10,在當前屏幕上視圖有10個像素寬度,但是在更高密度屏幕的設備上,返回值可能是15.如果在你的應用程序代碼中,使用像素值爲位圖的單位,且該位圖不是爲當前屏幕密度預先調整的,可能會調整這些在代碼中你用以匹配未調整的位圖源的像素值。

假設應用程序在運行時巧妙地處理位圖或像素值,請參閱下面的章節Additional Density Considerations。

3. 不要使用絕對佈局

不像其他的佈局部件,絕對佈局強制使用固定位置給子視圖佈局,這很容易導致用戶界面不能很好地工作在不同的屏幕上。正因爲如此,在Android1.5(API等級爲3)中已經棄用了絕對佈局。

相反,應該使用相對佈局,它會使用相對位置爲它的子視圖佈局。例如,可以指定按鈕部件應該在文本部件的右側。

4.使用尺寸和指定密度資源

雖然系統會基於當前屏幕配置調整你的佈局和繪圖資源,但是可以在不同屏幕尺寸上調整UI,且提供最優化的位圖繪圖給不同密度。這在本文的前面已經反覆強調過。

如果需要嚴格控制應用程序在各種屏幕配置上的顯示情況,那麼在指定配置資源目錄中調整佈局和位圖繪圖。例如,假設希望圖標顯示在中等和高密度屏幕上。簡單地創建兩個不同尺寸的圖標(例如100x100用於中等密度,150x150用於高密度),把這兩個變體放在適當的目錄,使用適當的限定符:

res/drawable-mdpi/icon.png //適合於中等密度屏幕

res/drawable-hdpi/icon.png //適合於高密度屏幕

注:如果密度限定符沒有定義在目錄名中,系統會假定在那個目錄裏的資源是爲基線中等密度設計的,將會適當地爲其他密度做調整。

更多關於有效的配置限定符的信息,請參閱本文前面結束的Using configuration qualifiers。

附加密度的注意事項

本節描述了更多關於系統如何在不同屏幕密度上調整位圖繪圖、以及如何更好地控制位圖在不同密度上的顯示信息。本節中的信息對大多數應用程序應該不是很重要,除非應用程序在不同屏幕密度上運行時或者應用程序篡改了圖像時,遇到了問題。 爲了更好地瞭解在運行過程中改變了圖像時如何做到支持多密度,應該瞭解,系統通過以下幾種方式確保合適的位圖尺寸:

1.預先調整的資源(如位圖繪圖)

基於當前屏幕的密度,系統使用應用程序中任何指定尺寸和密度的資源,並顯示出來且不需要任何調整。如果資源在當前密度不可用,系統將會下載默認資源並調整他們使之適合於當前屏幕密度。系統認爲默認資源(無配置限定符目錄的資源)是爲基準屏幕密度(mdpi)設計的,除非它們是從指定密度資源目錄下載的。預先調整是指調整位圖到當前屏幕密度適合的尺寸時系統所做的事情。
如果你請求預先調整好的資源的尺寸,系統會返回調整後代表該尺寸的值。例如,一個50x50 像素的mdpi屏幕的位圖要在hdpi屏幕上擴大爲75x75像素(如果此時沒有可替代資源給hdpi),系統會這樣返回此值。
有一些情況下,可能不需要Android的預先調整的資源。避免預先調整的最簡單方式是將資源放置到nodpi配置限定符的目錄中。例如:
res/drawable-nodpi/icon.png
當系統使用這個文件夾中的icon.png位圖時,它不會基於當前屏幕密度去調整該位圖。

2.像素尺寸和座標值的自動調整

應用程序可以通過在清單文件中設置android:anyDensity的屬性爲“假”或在程序中設置位圖的inScaled值爲“假”禁止預先調整資源。在這種情況下,系統在繪圖時會自動調整絕對像素的座標值和像素尺寸。這樣做的目的是,爲了確保已定義像素的屏幕元素仍然能以接近他們在基線屏幕密度(hdpi)上的物理尺寸顯示出來。系統透明地處理這種調整並把調整後的像素尺寸,而不是物理像素尺寸告訴應用程序。
例如,假設一個設備有WVGA高密度屏幕,即480x800,這與傳統的HVGA屏幕的尺寸大約相同,但是它運行着已禁止預先調整資源功能的應用程序。在這種情況下,當系統在查找屏幕尺寸時,它會“欺騙”應用程序,給它返回值320x533(轉化成屏幕密度接近mdpi)。然後,當應用程序開始繪圖操作時,如使矩形從(10,10) 擴大到 (100, 100)變成無效,系統通過縮放接近數量的值調整座標,且把區域(15,15) 擴大到 (150, 150)變成無效。如果你的應用程序直接使用這個調整後的位圖,這個誤差會導致不可預期的行爲,但是這被認爲是合理的折中的儘可能保持應用程序性能的方法。如果遇到這種情況,請閱讀下面關於Converting dp units to pixel units章節。
通常情況下,不應該禁止預先調整資源。支持多屏的最好方式是按照上面的How to Support Multiple Screens提到的基本技術操作。

如果應用程序在屏幕上以其它某種方式操作位圖或與像素直接交互,你可能需要採取額外的步驟來支持不同屏幕密度。例如,如果你通過數手指劃過時的像素值的方式響應觸摸,你需要使用適當的密度無關性像素值,而不是實際的像素值。

調整運行時創建的位圖對象

如果應用程序創建一個內存中的位圖(位圖對象),系統認爲這個位圖是爲基線中等密度屏幕設計的,默認情況下,在繪製時自動調整位圖。當位圖沒有指定密度特性時,系統採用“自動調整”技術。如果沒有正確地考慮到當前屏幕密度,也沒有指定位圖的密度特性,自動調整會導致人爲縮放,這與沒有提供可替代資源時一樣。

爲了控制在運行時創建的位圖是否需要調整,你可以通過setDensity()指定位圖的密度,從DisplayMetrics傳遞一個密度常量,比如DENSITY_HIGH 或 DENSITY_LOW。

如果正在創建一個使用BitmapFactory(如從文件或者流)的位圖,可以使用BitmapFactory。選擇定義一個已經存在的位圖的特性,這決定系統是否或如何調整位圖。例如,可以使用Density來定義位圖是爲哪種密度設計的,用Scaled去指定位圖是否應該調整到匹配當前設備的屏幕密度。

如果設置Scaled爲假,禁用了任何系統會用於位圖的預先調整功能,系統在運行時將會自動調整它。使用自動調整而不是預先調整會耗費更多CPU,但是佔用更少的內存。

scale-test.png

圖5 預先調整和自動調整位圖的演示比較結果

圖5 演示了當在高密度屏幕上下載低(120),中等(160) 和高 (240) 密度位圖時,預先調整和自動調整機制的結果。區別是微妙的,因爲所有的位圖都被調整以匹配當前屏幕密度,然而調整過的位圖的外觀稍微不同,這取決於在繪製時採用的是預先調整還是自動調整。你會找到此示例應用程序的源代碼,在ApiDemos裏,演示瞭如何使用預調整和自動調整位圖。

注:在Android3.0或者以上版本,由於圖形框架的改進,預先調整和自動調整位圖之間應該沒有明顯的差異。

-= 轉換dp單位爲像素單位 =-

在某些情況下,需要用dp來表示尺寸,然後把他們轉換爲像素。想象一下,在應用程序中滾動或者扔的手勢在用戶的手指劃過至少16像素後才能被識別出。在基準屏幕上,在手勢被識別出來之前,用戶必須劃過16像素除160dpi,這等於十分之一英寸(或者2.5毫米)。在一個高密度屏幕(240dpi)設備上,用戶必須劃過16像素除240dpi,即十五分之一英寸(或者1.7毫米)。這個距離相當短,因此對用戶來說,程序看上去更加敏感。

要解決這個問題,手勢閾值必須用dp表示,然後轉換成實際的像素。例如:

  1.    
  2. <span style="color:#808080; margin:0px; padding:0px"><em>// The gesture threshold expressed in dp</em></span>  
  3. <span style="margin:0px; padding:0px; font-weight:bold">private</span> <span style="margin:0px; padding:0px; font-weight:bold">static</span> <span style="margin:0px; padding:0px; font-weight:bold">final</span> <span style="color:#993333; margin:0px; padding:0px">float</span> GESTURE_THRESHOLD_DP = <span style="color:#cc66cc; margin:0px; padding:0px">16</span>.0f;  
  4.    
  5. <span style="color:#808080; margin:0px; padding:0px"><em>// Get the screen's density scale</em></span>  
  6. <span style="margin:0px; padding:0px; font-weight:bold">final</span> <span style="color:#993333; margin:0px; padding:0px">float</span> scale = getResources<span style="color:#66cc66; margin:0px; padding:0px">(</span><span style="color:#66cc66; margin:0px; padding:0px">)</span>.<span style="color:#0660; margin:0px; padding:0px">getDisplayMetrics</span><span style="color:#66cc66; margin:0px; padding:0px">(</span><span style="color:#66cc66; margin:0px; padding:0px">)</span>.<span style="color:#0660; margin:0px; padding:0px">density</span>;  
  7. <span style="color:#808080; margin:0px; padding:0px"><em>// Convert the dps to pixels, based on density scale</em></span>  
  8. mGestureThreshold = <span style="color:#66cc66; margin:0px; padding:0px">(</span><span style="color:#993333; margin:0px; padding:0px">int</span><span style="color:#66cc66; margin:0px; padding:0px">)</span> <span style="color:#66cc66; margin:0px; padding:0px">(</span>GESTURE_THRESHOLD_DP * scale + <span style="color:#cc66cc; margin:0px; padding:0px">0</span>.5f<span style="color:#66cc66; margin:0px; padding:0px">)</span>;  
  9.    
  10. <span style="color:#808080; margin:0px; padding:0px"><em>// Use mGestureThreshold as a distance in pixels...</em></span>  
  11.    

根據當前屏幕密度,DisplayMetrics.density指定了你必須使用的將dp單位轉爲像素單位的比例因子。在一箇中等密度屏幕上,DisplayMetrics.density等於1.0;在高密度屏幕上,DisplayMetrics.density等於1.5;在一個超高密度屏幕上,DisplayMetrics.density等於2.0;在低密度屏幕上,DisplayMetrics.density等於0.75.這個比例因子乘以dp單位得到的值就是當前屏幕的實際像素值(然後添加0.5f做四捨五入,轉化的整數)。更多信息,請參看DisplayMetrics類。

然而,不是爲這裏事件定義任意閾值,而是你應該使用預先調整的可從ViewConfiguration獲取的配置值。

使用預先調整的配置值

可以使用ViewConfiguration類去訪問Android使用的共同的距離、速度和時間。例如,框架使用的作爲滾動閾值的距離可通過getScaledTouchSlop()得到:

private static final int GESTURE_THRESHOLD_DP =ViewConfiguration.get(myContext).getScaledTouchSlop();

以前綴getScaled開頭的ViewConfiguration的方法保證返回值以像素爲單位,無論當前屏幕的密度是什麼,它都能正確顯示。

如何在多屏上測試你的應用程序

在發佈應用程序之前,應該在所有支持的屏幕尺寸和密度上徹底地測試應用程序。Android的SDK包含了你可以使用的模擬器,它複製了應用程序可以運行的通用的屏幕配置的尺寸和密度。可以修改模擬器默認的尺寸,密度和分辨率以複製任何指定屏幕的特徵。使用模擬器和額外的自定義配置讓你可以測試任何可能的屏幕配置,因此不必買各種設備來測試應用程序支持的屏幕。

爲了建立測試應用程序支持的屏幕環境,通過使用模擬器和模仿應用程序支持的屏幕的尺寸和密度的屏幕配置,應當創建一組AVDs(Android虛擬設備)。要做到這一點,可以使用AVD管理器去創建AVDs,然後以圖形界面方式啓動它們。

爲了啓動Android SDK管理器,在Android SDK目錄(在windows上)執行SDK Manager.exe或者在<sdk>/tools/目錄執行android。圖6展示了用來測試各種屏幕配置的選擇了AVDs的AVD管理器。

avds-config.png

圖6展示了用來測試各種屏幕配置的選擇了AVDs的AVD管理器。

更多有關創建和使用AVDs測試應用程序的信息,請參閱Managing AVDs with AVD Manager。

表3 Android SDK中從模擬器獲取的各種屏幕配置和其它典型的分辨率

  Low density (120), ldpi Medium density (160), mdpi High density (240), hdpi Extra high density (320), xhdpi

Small screen

QVGA (240x320)

 

480x640

 

Normal screen

WQVGA400 (240x400)WQVGA432 (240x432)

HVGA (320x480)

WVGA800 (480x800) WVGA854 (480x854) 600x1024

640x960

Large screen

WVGA800** (480x800)WVGA854** (480x854)

WVGA800* (480x800) WVGA854* (480x854) 600x1024

   

Extra Large screen

1024x600

WXGA(1280x800)† 1024x7681280x768

1536x1152 1920x1152 1920x1200

2048x1536 2560x1536 2560x1600

* 爲了模仿此配置,在創建一個使用WVGA800或者WVGA854外觀的AVD時指定.自定義的密度爲160.
**爲了模仿此配置,在創建一個使用WVGA800或者WVGA854外觀的AVD時指定.自定義的密度爲120
† 這個外觀是Android3.0平臺可用的. 

想要知道支持任何給定屏幕配置的有源設備的相對數量,請參看屏幕尺寸和密度儀表板。

我們也建議在物理尺寸接近匹配的實際設備的模擬器上測試應用程序。這使得比較各種尺寸和密度上的測試結果變得非常容易。做到這點,需要知道電腦顯示器(例如,30寸的Dell顯示器的密度大約爲960dpi)的以dpi爲單位的近似密度。當從AVD管理器啓動AVD時,可以在啓動選項中,如圖7所示,指定模擬器的屏幕尺寸和顯示器的dpi。

avd-start.png

圖7 當從AVD管理器啓動AVD時,你能設置的尺寸和密度

如果想在內置外觀不支持的分辨率或密度的屏幕上測試應用程序,可以創建一個使用自定義分辨率或密度的AVD。在創建AVD時,應指定分辨率,而不是選擇內置的外觀。

如果正通過命令行啓動AVD,可以指定通過選項參數-scale來指定比例。例如:

emulator -avd <avd_name> -scale 96dpi

爲了改變模擬器的大小,可以通過參數選項選擇想要的比例因子0.1-3實現。

更多關於從命令行創建AVDs的信息,請參閱Managing AVDs from the Command Line。

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