SupportingMultiple Screens(支持多屏幕)

SupportingMultiple Screens(支持多屏幕)

安卓運行在不同尺寸和屏幕密度的設備上。對於程序來說,安卓系統提供統一的開發環境並且處理程序界面在屏幕上顯示的大部分工作。

同時,爲了優化在不同屏幕配置上的UI設計,系統也提供api允許你的程序給特定尺寸和密度的屏幕指定界面。例如,在平板和手機上你想要不同的界面。

雖然系統會爲了你的程序適應不同屏幕縮放和改變大小,你也應該爲不同屏幕尺寸和密度的設備優化你的程序。

這個時候,你在所有設備上都重視用戶體驗那麼你的用戶認爲你的程序確實是爲他們的設備設計的而不是簡單的在他們的設備上進行伸縮。

按照下面文檔裏的練習,你可以用一個簡單的apk文件創建一個程序並且在其支持的所有設備上很好的顯示和提供一個優化的用戶體驗。

注意:文檔中的信息假定你的程序是安卓1.6或更高版本,如果你的程序支持安卓1.5或者更低,請先閱讀Strategies for Android 1.5.同樣,請注意從安卓3.2開始引入了一些新的api允許你更精確的控制給不同尺寸的屏幕提供的佈局資源。如果你正在給運行在平板上的程序做優化這些新的特性尤其重要。更多詳情,請看Declaring Tablet Layouts for Android 3.2.部分。

屏幕支持概述

這一部分提供安卓支持不同屏幕的概述,包括:在文檔和api中術語和概念的介紹,系統提供的屏幕配置的摘要,api概述和向下的屏幕兼容特性。

術語和概念

屏幕尺寸:實際的物理大小,通過屏幕對角線測量。爲了簡化,安卓把所有的屏幕尺寸歸類爲四種尺寸:small,normal,large和extra-large。

屏幕密度:屏幕上一個物理區域像素的數量;通常dpi(每英寸有多少像素點),例如,“low”密度的屏幕在單位物理區域上的像素比“normal”和“high”更少。

爲了簡化,安卓將屏幕密度歸類爲六種密度:low, medium, high, extra-high, extra-extra-high, 和extra-extra-extra-high

向:用戶使用view時屏幕的方向。橫向或者是縱向,意思就是說屏幕的方向比例是更寬還是更高。

Be aware that not only do different devices operate in different orientations by default,當用戶旋轉設備時設備的方向會變化。

分辨率:一個屏幕上所有物理像素的總數。當增加對多種屏幕的支持時,程序不會直接對分辨率起作用;程序應該只關心所處歸類分組的尺寸和密度

密度-獨立像素(Density-independentpixel (dp))

        虛擬的像素單位,定義用戶界面佈局時使用,用密度獨立的方法表示佈局大小或者位置。

        密度獨立像素和160dpi屏幕上一個物理像素是相同的,160dpi的密度是基線密度也就是系統假定的“medium”的屏幕密度。

        在運行時,基於使用中實際的屏幕密度系統會控制dp單位的縮放。dp單位和屏幕密度的轉換非常簡單:px=dp*(dpi/160)即:px/dp=dpi/160

        例如:在一個240dpi的屏幕上,1dp等於1.5物理像素。爲了確保在不同密度的屏幕上適當的展現你的用戶界面,當你定義用戶界面時應該使用dp單位。

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

從安卓1.6開始,考慮到設備可能有許多不同的屏幕配置,安卓提供多屏幕尺寸和密度支持。

        你可以利用安卓系統的特性來給不同屏幕配置進行界面優化,保證你的程序不僅僅只是顯示出來而是在不同屏幕上提供最好的用戶體驗。

        爲了簡化給不同屏幕設計界面,安卓將實際的尺寸和密度分爲:

        四組尺寸分類:small, normal,large, and xlarge

        注意:從安卓3.2開始,這個尺寸分類被新的基於可以屏幕寬度的屏幕管理技術取代。

        如果你開發的app是3.2或者更高,參看Declaring Tablet Layouts forAndroid 3.2

        六組密度分類:

        ldpi (low) ~120dpi

        mdpi (medium)~160dpi

        hdpi (high) ~240dpi

        xhdpi (extra-high)~320dpi

        xxhdpi(extra-extra-high) ~480dpi

        xxxhdpi(extra-extra-extra-high) ~640dpi

尺寸和密度的分類都是基於normal大小和mdpi密度而演化而來的。normal大小和mdpi密度的配置是第一臺安卓手機的配置-T-Mobile G1。

T-Mobile G1有一個HVGA的屏幕(直到安卓1.6,這是安卓唯一支持的屏幕)

每個尺寸和密度的分類都表示一個範圍的屏幕尺寸和密度,例如,兩個設備都有normal的屏幕尺寸但是手動測量他們實際的屏幕尺寸和方向比例還是會有輕微的不同。

同樣兩個都是hdpi密度的屏幕實際測量的像素也可能有輕微差別。安卓給程序做出區分,你就可以給不同分類設計用戶界面最終讓系統來進行適配。

圖1表示了不同的尺寸和屏幕密度是如何被安卓粗略分成不同類的尺寸和密度的。


就像你給不同屏幕設計UI,每個設計都有一個最小空間的要求。上面每個屏幕尺寸的分類都有一個系統規定的最小分辨率。這個最小尺寸是用dp做單位

和你定義佈局使用的單位相同,這樣就不用擔心屏幕密度的變化。

xlarge screens are at least960dp x 720dp

large screens are at least640dp x 480dp

normal screens are at least470dp x 320dp

small screens are at least426dp x 320dp

注意:這些最小屏幕尺寸在安卓3.0之前是沒有定義的,所以你可能遇到一些處於normal和large之間的設備是錯誤的分類。

這個通常基於屏幕的物理分辨率,因此可以跨越設備。例如一個1024*720的平板上面有系統欄(system bar)由於使用系統欄所以用於程序的空間就會少一點。

爲了給不同屏幕尺寸和密度優化程序UI,你可以給尺寸和密度分類提供可選資源。針對有代表性的屏幕,你可以提供可選的佈局給不同屏幕尺寸,

可選的bitmap圖像給不同的分辨率。在運行時,系統會基於當前屏幕所在的尺寸和密度分類爲應用選擇合適的資源。

你不需要爲每一個屏幕尺寸和密度組合提供可選資源。系統提供了強大的兼容特性在絕大多數屏幕上都可以處理你的應用的展示

提供運用調整大小技術所設計的UI(就像下面Best Practice描述的)

注意:概括一個設備的屏幕尺寸和密度特徵要和其他進行區分。

例如,一個WVGA high-density屏幕被認爲是一個normal尺寸因爲它的物理尺寸和T-Mobile G1(安卓第一部手機也是屏幕的基線配置)相同。

另一方面,一個WVGA  medium-density屏幕被看作是一個large尺寸的屏幕。雖然提供相同的分辨率(相同數量的像素),WVGA  medium-density

有更低的屏幕密度,意味着每個像素會更大,所以屏幕大小要比基線屏幕(normalsize)大。

密度獨立

        Your application achieves"density independence" when it preserves the physical size

        (from the user's point of view) ofuser interface elements when displayed on screens with different densities.

維護密度獨立是很重要的,否則一個界面元素(例如一個button)在低密度屏幕上很大在高密度屏幕就會很小。如果這樣在你應用的佈局和可用性上都會出現問題。

圖2和圖3分別展示了提供密度獨立和不提供密度獨立的情況

安卓系統可以在兩方面幫助你的應用實現密度獨立:

1、針對當前屏幕密度系統對dp單位進行縮放

2、如果有必要,系統會基於當前屏幕密度對drawable資源進行縮放

在圖2中,TextView和bitmap drawable是用px單位定義的,所以view在低密度屏幕大高密度屏幕小。即使屏幕尺寸相同高密度屏幕會有更多的像素點在單位面積上。

在圖3中,佈局大小用dp指定。因爲基線密度-獨立像素是medium-density屏幕,所以在具有medium-density密度的屏幕上看起來和圖2中medium-density屏幕是一樣的。

對於不同密度的屏幕,系統會縮放密度獨立像素的值,來適配屏幕。

大多數情況,你可以根據情況簡單的指定所有佈局的大小用dp或者“wrap_content”來保證密度獨立。

系統會根據當前屏幕密度適當的縮放bitmap drawable來做展示。

不管怎樣,bitmap縮放會是bitmap變得模糊,你也許在上面的截圖中注意到了。爲了避免,你應該給不同的密度提供不同的bitmap資源。

例如,給高密度屏幕提供高分辨率bitmap,系統將會使用這些而不是將medium-density進行縮放。下面的部分介紹更多的如何給不同屏幕密度提供可選資源。

如何支持多種屏幕

對於不同程序不同屏幕配置選擇適當的佈局和bitmap drawable是安卓支持多屏幕的基礎能力。

系統處理大多數工作使程序合適的展現在不同的屏幕配置上通過縮放佈局來適配屏幕尺寸/密度,縮放bitmap drawable來適應屏幕密度。

要更優雅的處理不同屏幕配置,你應該:

*在配置文件中明確聲明你的應用支持的屏幕尺寸

聲明你的應用支持哪些屏幕尺寸,確保你唯一支持屏幕的設備可以下載你的程序。聲明支持不同的屏幕尺寸同樣可以影響系統如何在大屏幕上繪製你的程序,

不管你的程序是否是在屏幕兼容模式下運行。

聲明你的應用的屏幕支持尺寸,你可以在配置文件<supports-screens>中指定

*給不同屏幕提供不同佈局

默認情況下,安卓會根據當前設備屏幕調整程序。大多數情況都沒問題。少數情況你的用戶界面看起來不夠好並且需要爲屏幕調整界面。

例如,在一個大的屏幕上,你可能像調整一些元素的位置和尺寸來利用額外的空間,或者在一個小屏幕上,你也可能要調整尺寸讓內容都可以顯示出來。

你可以用來進行尺寸限定的的資源是 small,normal,large和xlarge。例如,給超大屏幕用的佈局應該放在 layuout-xlarge/

從安卓3.2開始,上面的尺寸集合被不再被推薦使用,你應該使用sw<N>dp表示你佈局資源的最小可用寬度。

例如,如果你的多窗口平板佈局需要至少600dp的屏幕寬度,你應該把它放在layout-600dp/下。

關於使用這項新技術聲明佈局資源進一步的討論參照Declaring Tablet Layouts for Android 3.2.

*給不同屏幕密度提供不同的bitmap drawable

默認情況下,安卓縮放bitmapdrawables(.png, .jpg, and .gif 文件)和Nine-Patch drawables (.9.png 文件)以便於在每種物理尺寸的設備上展現出來。

例如,如果你的程序置爲基線設備提供bitmapdrawable,medium 屏幕密度(mdpi),系統將在一個高密度屏幕上對他們進行放大,在一個低密度屏幕設備上縮小。

This scaling can causeartifacts in the bitmaps。確保bitmap能很好的展現,你應該給不同分辨率屏幕提供不同解決方案。

配置分類(下面將詳細介紹)你可以用來指定屏幕密度的有

ldpi (low), mdpi (medium),hdpi (high), xhdpi extra-high), xxhdpi (extra-extra-high), and xxxhdpi(extra-extra-extra-high)

例如,給高密度屏幕使用的bitmap應該放在drawable-hdpi/下。

注意:mipmap-xxxhdpi限定詞是僅僅需要提供一個應用圖標,比在一般xxhdpi設備上會更大。不需要給應用所有圖像提供xxxhdpi資源

一些設備會放大應用圖標差不多25%。例如,如果你最高密度應用圖標圖像是extra-extra-high-density。

the scaling process willmake it appear less crisp壓縮過程將會

你應該在mipmap-xxxhdpi目錄提供一個更高密度的應用圖標,系統就避免將一個小的圖標放大。

更多信息參看Provide anxxx-high-density launcher icon。除了應用圖標其他用戶界面你不能使用xxxhdpi限制符

注意:將所有應用圖標放在res/mipmap-[density]/文件夾下而不是res/drawable-[density]/下。安卓在密度指定的文件夾下保持資源,

                  比如mipmap-xxxhdpi,不管安裝在什麼樣分辨率的屏幕上。這個設計允許桌面程序選取最佳分辨率的圖標在主頁面顯示。

                  跟多信息參看Managing Projects Overview.

尺寸和密度的配置限制符和上面的Rangeof screens supported是一致的

注意:如果你不熟悉配置限定符和系統如何用可選資源,請閱讀 Providing Alternative Resources獲得更多信息

運行時,系統會根據提供的資源按照下面步驟達到最好的展現:

1、系統使用合適的可選資源

             基於當前屏幕的尺寸和密度,系統使用你的程序提供的尺寸和密度指定的資源。例如,如果設備是高密度屏程序需要一個drawable資源,

             系統會查找和設備配置最佳匹配的drawable資源文件目錄。根據其他可用的可變資源,如果hdpi資源目錄(比如drawable-hdpi/)有可能是最佳匹配的,

             系統就會使用這個文件夾下的資源。

2、如果沒有匹配的資源可用,系統使用默認的資源並且進行縮放來匹配當前屏幕

             默認資源是沒有配置限定標記的。例如,在drawable/下的資源就是默認的資源。系統假定默認資源是按照基線設備(normal屏幕,medium密度)尺寸和密度設計的,。

             同樣系統會在高密度屏幕和低密度屏幕上對默認密度資源進行適當的放大和縮小。

             無論如何,當系統在密度指定文件夾下沒有找到密度指定資源,系統不會每次都使用默認資源。爲了有更好的縮放效果系統可能會使用另一個密度指定的文件夾資源。

             例如,當我們要尋找的low-密度資源不可用,系統跟傾向於將high密度的資源進行縮放,因爲系統將一個high密度的資源縮小到0.5比將一個medium密度資源縮小到0.75更容易。

     更多關於安卓如何選擇可選資源來匹配設備配置的配置限定請閱讀How AndroidFinds the Best-matching Resource.

使用配置限定符

              安卓支持多個配置限定符,允許你自己根據當前屏幕特徵控制系統如何選擇可選資源。

              配置限定符是一個你可以添加到你安卓應用目錄並且給在目錄中設計好的文件指定配置的字符串。

              使用配置限定符:

              1、在res/文件夾下創建目錄並且按照以下格式命名:

              <resources_name>-<qualifier>

              <resources_name>是標準的資源名稱(比如drawable或者layout)

              <qualifier>是下面表格1中的配置限定符,給使用的資源(比如hdpi或者xlarge)指定指定屏幕配置

              可以使用多個限定符中間用-隔開

              2、在新的目錄保存合適的配置指定資源。資源文件命名必須和默認資源文件結構相同。

              例如,xlarge是extra-large屏幕的配置限定符。當你把限定符加到資源目錄名稱後(比如layout-xlarge),這樣就告知系統這些資源是用在有extra-large屏幕的設備上的。

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




注意:如果你的程序運行在安卓3.2或者更高,參看Declaring Tablet Layouts for Android 3.2獲取更多關於新的配置限定符用於指定不同屏幕尺寸的佈局資源。(替代表1中的尺寸限定符)

更多關於這些限定符是指的屏幕尺寸和密度的粗略範圍,參見Range of Screens Supported在文檔的前面。

例如,下面的程序資源目錄給不同屏幕尺寸和不同的drawable提供不同的佈局設計。mipmap/文件夾用來放應用圖標。

res/layout/my_layout.xml              //正常屏幕尺寸佈局 (默認)
res/layout-large/my_layout.xml        //大屏幕尺寸佈局
res/layout-xlarge/my_layout.xml      // X大屏幕尺寸佈局
res/layout-xlarge-land/my_layout.xml  //橫向X大屏幕尺寸佈局


res/drawable-mdpi/graphic.png        //正常密度bitmap
res/drawable-hdpi/graphic.png        //高密度bitmap
res/drawable-xhdpi/graphic.png        // X高密度bitmap
res/drawable-xxhdpi/graphic.png      // XX高密度bitmap

res/mipmap-mdpi/my_icon.png        //正常密度應用圖標
res/mipmap-hdpi/my_icon.png        //高密度應用圖標
res/mipmap-xhdpi/my_icon.png        // X高密度應用圖標
res/mipmap-xxhdpi/my_icon.png      // XX高密度應用圖標
res/mipmap-xxxhdpi/my_icon.png      // XXX高密度應用圖標

更多信息關於如何使用可選資源和配置限定符的完整列表(不僅僅包括屏幕配置)參看Providing Alternative Resources.

意識到,當安卓系統運行時選擇資源時,它用一些邏輯來確定最佳資源。That is, the qualifiers you use don't have to exactly match the currentscreen configuration in all cases in order for the system to use them. (你使用的限制符沒必要爲了給系統使用而把當前屏幕配置的所有分類限定符都寫出來)。

特別是,當基於尺寸限定符選擇資源時,如果沒有和當前屏幕匹配的系統會選擇比當前屏幕小的資源(例如,如果有必要large-size屏幕使用normal-size屏幕資源)。然而,當唯一可用資源比當前屏幕大,程序不會使用這些資源,如果沒有其他和屏幕配置匹配的資源程序將會崩潰(例如,如果所有佈局資源都被xlarge限定符標記,但是設備是normal-size 屏幕)。更多關於系統如何選擇資源的信息,請閱讀How Android Finds the Best-matching Resource.

提示:如果你有一些系統不能縮放的drawable資源(獲取你在程序運行是對圖片進行了調整),你應該把他們放到nodpi配置限定符文件夾下。這個文件夾下的資源被認爲是密度不可知的系統不會縮放他們。

設計可選佈局和drawable

       根據程序需要你應該提供各種類型的可選資源。通常,你應該使用尺寸和方向限定符來提供可選佈局資源,密度限定符來提供可選bitmap drawable資源。

下面的部分總結如何分別使用尺寸和密度限定符來提供可選佈局和drawables。

可選佈局

通常,當你在不同設備配置上測試你的程序時你會知道你是否需要不同屏幕尺寸的可選佈局。例如:

*當在小屏幕上測試,你可能會發現你的佈局不能很好的適配屏幕。例如,在一個小屏設備上一行的button可能放不下。在這個例子中你應該給小屏幕提供可選佈局來給button提供合適的尺寸和位置。

*當在xlarge尺寸屏幕測試時,你應該認識到你的佈局是明顯拉伸來適配大屏幕的。在這個例子中你因該給xlarge屏幕提供可選佈局,提供一個給大屏比如平板重新設計的UI。

雖然你不提供可選佈局給大屏你的程序也不會出現問題。但你的程序看起來是給他們設備專門做的對於用戶來說是非常重要的。如果UI明顯看起來是被拉伸的用戶可能會對程序產生不滿。

*如果在橫豎屏上進行對比測試,你應該注意在豎屏上底部的按鈕應該在橫屏上放在右邊。

總結,你因該確認你的佈局:

*適配小屏幕(用戶實際上可以使用你的應用)

*針對大屏幕優化,利用增加的屏幕空間

*優化橫豎屏

如果你的UI使用bitmap來適配一個view甚至是系統縮放後(像一個button的背景圖片),你應該使用nine-patch bitmap文件。nine-patch文件是基於png文件,你需要在nine-patch文件中指定兩個拉伸的區域。當系統想縮放使用了bitmap的view時,系統拉伸nine-patch圖片,僅僅拉伸指定的區域。像這樣就不用給不同屏幕尺寸提供不同的drawable,因爲nine-patch可以調整到任何尺寸。你應該給不同屏幕密度提供不同的nine-patch文件。

可選drawable

幾乎每個程序都給不同屏幕密度設備提供可選drawable資源,因爲幾乎每個程序都有應用圖標並且圖標應該在所有屏幕分斌率下都顯示良好。同樣的,如果你的程序中有其他的bitmap drawable(比如菜單的圖標或者其他圖形),你應該給不同分辨率提供可選的版本或者每個分辨率都提供一個。

注意:你只需要提供密度指定的drawable,bitmap(.png.jpg, or .gif)或者nine-patch(.9.png

如果使用xml文件來定義sharpe,colors或者其他drawable資源,你應該放一個默認的副本在默認drawable文件夾下(drawable/)。

爲不同密度創建可選bitmap drawable,在六個常用的密度中你應該遵守3:4:6:8:12:16縮放比率。

例如,如果你有一個48像素*48像素的bitmapdrawable提供給medium密度屏幕,所有其他尺寸應該是:


·  36x36 (0.75x) for low-密度

·  48x48 (1.0x baseline) for medium-密度

·  72x72 (1.5x) for high-密度

·  96x96 (2.0x) for extra-high-密度

·  180x180 (3.0x) forextra-extra-high-密度

·  192x192 (4.0x)for extra-extra-extra-high-密度 (只用於圖標; 看上面的提示)

更多關於設計圖標的信息,參看 Icon Design Guidelines,其中包含各種bitmap drawable的尺寸信息,像應用圖標,菜單圖標,狀態欄圖標,標籤圖標等等。

給安卓3.2聲明平板佈局

第一代平板運行安卓3.0,聲明平板佈局應該將他們放在xlarge的限制符文件夾下,(例如,res/layout-xlarge/)。爲了適應其他類型的平板尤其是屏幕尺寸,7寸平板-安卓3.2爲分散的屏幕尺寸引入了一個新的指定資源的方式。這種新技術基於佈局需要的空間總數(例如寬度600dp)而不是讓佈局來填充分類的尺寸(例如large或xlarge)。

給7寸平板設計設計的原因是7寸平板和5寸手機在之前的分類中屬於同一類(large分類)。這兩個設備看起來尺寸接近,但是給程序提供的空間是不同的,as isthe style of user interaction(是用戶交互的樣式)。這樣 7寸和5寸不應該用同樣的。安卓現在允許你基於以dp爲單位的寬度或者高度來給你的應用指定不同佈局資源這樣就可以給這兩個種類屏幕提供不同佈局。

例如,當你給平板樣式的設備設計完佈局後,你可能覺得這個佈局這個佈局在寬度小於600dp設備上不會很好的顯示。這個成爲了給你的平板佈局提供的最小值。同樣的,你可以指定你程序UI的佈局資源應該使用在寬度至少600dp的屏幕。你可以選一個寬度作爲你的最小寬度來設計或者測試你的佈局支持的最小寬度。

注意:所有的使用了新尺寸的APIs都是密度獨立像素(dp)值你佈局的尺寸也應該定義成dp單位,because what you care aboutis the amount of screen space available after the system accounts for screendensity (as opposed to using raw pixel resolution) 因爲你應該關心的是屏幕可用空間總量而不是佔屏幕密度的比例(和使用像素密度相反)

使用新的尺寸限定符

根據可用屏幕空間給佈局指定不同的資源配置如表2所述。新的限定符比起指定支持的屏幕尺寸能讓你更多的控制,相比較傳統的屏幕空間(small, normal, large, 和 xlarge)

注意:你使用限定符指定的尺寸不是真的屏幕尺寸。而是Activity所在窗口的可用dp單位。安卓系統會將一部分屏幕空間來顯示UI(例如頂部的狀態條和底部的系統條),有一些屏幕空間不是給佈局使用的。這樣你聲明的尺寸指的是Activity需要的大小,當給佈局聲明空間是系統會給系統UI留出一部分空間。Actionbar是程序界面空間的一部分,雖然你的佈局不需要聲明,所以他會減少屏幕可用空間設計界面時應留出空間。

表2屏幕尺寸的配置限定符(安卓3.2引入)

 




更多關於尺寸限定符的討論,參見Providing Resources文檔。使用這些限定符可能比使用屏幕分類更加困難,一旦你決定了你的需求這種方式是很簡單的。當你設計你的UI,你主要關心的事情是確切的尺寸你的應用在手機模式和平板多窗口模式做出選擇。選擇的準確點取決於獨特的設計或許你需要給你平板佈局720dp的寬度,或許600dp就夠了或許480dp,或者這些中間的一些。使用表2中的限定符,你的佈局改變時你能準確掌控尺寸。

配置舉例

幫助你給不同設備設計,這兒有一些典型的屏幕寬度:

*320dp:一個典型的手機屏幕(240x320ldpi, 320x480 mdpi, 480x800 hdpi等)

*480dp:atweener tablet like the Streak (480x800 mdpi)

*600dp:7寸平板(600*1012 mdpi)

*720dp:10寸平板(720x1280 mdpi, 800x1280 mdpi等)

使用表2中的尺寸限定符,程序能從手機和平板的不同佈局資源中進行選擇無論佈局高度和寬度。例如,如果600dp是你的平板佈局支持的最小可用寬度,你可以提供兩個佈局的集合:

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

在這個例子中,可用屏幕空間最小寬度一定是600dp爲了讓平板佈局能夠應用。

其他的例子中你想在7寸和10寸平板上都深度定製UI,你可以增加最小寬度佈局:

res/layout/main_activity.xml          # For handsets (smaller than 600dpavailable 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)

注意前面兩個資源集合使用了“smallest width”限定符,sw<N>dp,指定了屏幕兩邊中最小的一邊,不管屏幕當前的方向。這樣,使用sw<N>是一個忽略屏幕方向爲佈局指定屏幕全部可用尺寸簡單的方法。

然而,在一些例子中,對於你的佈局重要的是確定當前可用的寬和高。例如,如果你有兩個fragment並排的兩個窗口布局,你可能在屏幕最小寬度是600dp時使用這個佈局,不管設備是橫屏還是豎屏。在這個例子中,你的資源可能是這樣的:

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

注意第二個集合使用了“available width”限定符,w<N>dp,這種方式,一個設備可以精確使用兩種佈局,取決於屏幕方向(如果在一個方向上可用寬度最小是600dp而另外一個方向小於600dp)。

如果可用高度也是你關心的,你可以類似的使用h<N>dp限定符。或者,結合w<N>dp 和 h<N>dp以如果需要非常具體的指定。

聲明屏幕尺寸支持

一旦你給不同屏幕尺寸實現了佈局,在配置文件中聲明你要支持的屏幕是同樣重要的。

隨着新的屏幕尺寸限定符,安卓3.2給配置元素<supports-screens>引入了新的屬性:

android:requiresSmallestWidthDp

指定了需要的最小寬度。最小寬度是屏幕空間的最短尺寸(dp單位)並且對你的程序UI是可用的,可用屏幕空間兩邊中最短的。爲了讓一個設備被認爲兼容你的程序,設備的最小寬度必須相等或者大於這個值。(通常,你提供的你佈局所支持的最小寬度,不管屏幕當前方向)

例如,如果你的程序僅僅給最小可用寬度爲600dp的平板設備使用:

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

不管怎樣,如果你的程序支持安卓支持的所有屏幕尺寸(像426dp*320dp一樣小),你不需要聲明這些屬性,因爲你程序需要的最小寬度在任何設備上都是最小的。

警告:安卓系統不會重視這些屬性,所以他不會影響你的程序運行時的行爲。反而,他用來給你的程序過濾設備例如谷歌商店。然而,谷歌商店當前不支持這個屬性來過濾(在安卓3.2),所以如果你的應用不支持小屏幕,你應該繼續使用其他尺寸屬性。

android:compatibleWidthLimitDp

這個屬性允許你開啓屏幕兼容模式作爲一個用戶可選屬性用來指定你的程序支持的最大的“最小寬度”。如果設備可用屏幕的最短邊你的值還要大,用戶也可以安裝程序,但是會在屏幕兼容模式運行。默認情況下,屏幕兼容模式是關閉的你的佈局要調整大小來適應屏幕,但是系統條上的一個按鈕變成可用,允許用戶開啓或關閉屏幕兼容模式。

注意:如果你的程序佈局可以在大屏幕上很好的調整大小,你不需要使用這個屬性。我們建議你不要使用這個屬性而是按照文檔中的建議確保你的佈局可以在大屏幕上很好的展示。

android:largestWidthLimitDp

這個屬性允許你強制開啓screen compatibility mode 指定     你的程序支持的 “最小寬度”的最大值。如果設備可用屏幕的最小邊比你的值還大,程序運行在屏幕兼容模式,用戶不可關閉。

注意:如果你的程序能在大屏幕上合適調整大小,你不需要使用這些屬性。我們建議你避免使用這個屬性而是確保按照文檔裏的建議你的佈局能在大屏幕上調整大小。

警告:當開發安卓3.2和更高的版本,你不用把老的屏幕尺寸屬性和上面列表的屬性混合使用,新舊屬性混合使用可能會導致不明情況。

關於這些屬性中每個的更多信息,在各自鏈接中查看。

最好的練習

支持多屏幕的目標就是創建的應用能正確運行並且在安卓支持的所有屏幕上都可以適配。文檔前面的部分提供關於安卓如何讓你的應用適應屏幕和如何在不同屏幕上定製界面。前面部分的一些提示和技術概要可以確保你的應用在不同屏幕上合理的縮放。

這有一個關於怎樣確保你的應用在不同屏幕上合理展示的快速預覽清單:

1、使用wrap_contentfill_parent或者dp單位當在xml文件中指定大小時

2、在程序代碼中不要使用px硬編碼

3、不要使用絕對佈局(已經廢棄)

4、給不同屏幕密度提供可選bitmapdrawables

下面的部分將詳細介紹

1、使用wrap_contentfill_parent或者dp單位給佈局尺寸

當給xml文件中的view中定義android:layout_width 和 android:layout_height時,使用wrap_contentfill_parent或者dp單位可以保證view在當前設備屏幕上有合適的尺寸。

例如,一個view使用layout_width="100dp"那麼它的寬度中密度屏幕上是100px在高密度屏幕上就是150px,view會在屏幕上佔據相近的物理空間。

類似的,你應該用sp(scale-independent pixel)來定義字體大小。sp的縮放比例根據用戶的設置和系統的縮放類似dp

2、在程序代碼中不要使用px硬編碼

爲了展示和保持代碼簡潔,安卓系統使用像素作爲標準單位用來表示尺寸和座標值。這意味着一個view通常基於當前屏幕密度的尺寸在代碼中用像素表示。例如,如果myView.getWith()返回10,這個view在當前屏幕上是10像素寬,但是如果在高密度的屏幕上可能就是15。如果你在程序中用像素值對bitmap編碼,並且沒有針對當前屏幕進行預先縮放,你要對未縮放的bitmap資源通過縮放後的像素再定義。

如果你的程序操作bitmap或者運行時用像素值來定義,請參看下面部分Additional Density Considerations.

3、不要使用絕對佈局

和其他佈局不同,絕對佈局強制在子view上使用固定的位置,

附加密度

這節將更多的描述安卓如何在不同屏幕分辨率上縮放bitmap drawable和進一步控制bitmap在不同密度上的繪製。本節中的內容對於大部分程序來說不太重要,除非你的程序在不同屏幕密度設備上運行時遇到問題或者當你的程序處理圖像時。

爲了更好的理解運行時如何操縱圖像來支持多種密度的屏幕,你應該明白系統會幫助確認bitmap合適的縮放比例通過下面方法:

1、提前縮放資源(像bitmapdrawables)

基於當前屏幕的密度,系統從你的程序使用任何一個尺寸或者密度指定的資源無縮放的展示他們。如果資源對於正確的密度是無效的,系統加載默認的資源並進行縮放來匹配當前屏幕密度。系統假設默認資源(沒有配置限定符的目錄)是給基線屏幕密度設計的,除非從一個密度指定的資源目錄。提前縮放是這樣的,調整bitmap到合適的尺寸來適應當前屏幕密度。

如果你要獲取提前縮放資源的大小,返回值是縮放後的值。例如一個bitmap設計成50*50像素提供給mdpi屏幕在hdpi屏幕上縮放成75*75像素(如果沒有提供給hdpi的可選資源)系統同樣的記錄這個尺寸。

有一些情況你可能不想讓安卓預先縮放資源。不讓系統縮放資源簡單的方法是將資源文件放在nodpi配置限定符的資源文件夾。例如:

res/drawable-nodpi/icon.png

當系統使用這個目錄下的icon.png,在當前屏幕密度上不會縮放。

2、自動縮放大小和座標的像素

程序可以通過在配置文件中設置android:anyDensity爲 "false"或者以變成方式設置bitmap的inScaled 爲 "false"

在這個例子中,系統自動縮放任何一個絕對像素座標和座標大小值在繪製時。這樣做爲了確定用像素表示的屏幕元素仍然展示和基線屏幕密度(mdpi)近似的物理大小。The system handles thisscaling transparently to the application and reports the scaled pixeldimensions to the application, rather than physical pixel dimensions.系統掌握程序明顯縮放且記錄程序縮放的像素大小,而不是物理尺寸大小。

例如,假設一個設備有一個WVGA的高密度屏幕,480*800和一個慣例的HVGA屏幕有一樣的尺寸,它上面運行的程序關閉了提前縮放。在這個例子中,當查詢屏幕大小時系統將會對程序撒謊,報告是320*533(屏幕的密度將被轉化爲近似mdpi)。然後,當程序在做繪製(draw)操作時,例如讓從(10.10)到(100.100)的矩形無效,通過縮放他們合適的數量來轉換座標,實際使無效區域是從(15.15)到(150.150)。這個差距可能出現超出預料的顯示如果程序直接操縱縮放的bitmap,但這被認爲是保持程序很好展現的一個合理的交易。如果你遇到這個情況,閱讀下面部分的Converting dp units to pixel units.

通常,你不要關閉提前縮放。支持多屏幕最好的方式遵守基礎技術描述在上文的How to Support Multiple Screens.        

如果你的程序操作bitmaps或者在一些其他方法上直接和屏幕上的像素交互,你可能需要有附加的步驟來支持不同的屏幕密度。例如,如果你通過手指劃過的像素數量來響應手勢,你需要使用密度-獨立像素值來替代使用實際的像素。

縮放運行時產生的Bitmap對象

如果你的程序創建一個在內存中的bitmap(一個Bitmap對象),系統會假定是給基線medium-density屏幕設計的,默認情況下,繪製時會自動縮放bitmap。系統給一個Bitmap聲明auto-scaling當bitmap沒有指定密度屬性。如何你沒有正確的解釋當前設備屏幕密度和指定bitmap的密度屬性,auto-scaling可以導致scalingartifacts和你不提供可選資源一樣。

來控制運行時創建的Bitmap是否縮放,你可以指定Bitmap的密度用setDensity(),通過DisplayMetrics可以獲得一個密度常量,像DENSITY_HIGH或者DENSITY_LOW

如果你使用BitmapFactory創建Bitmap,像從一個文件或者從一個流你可以使用BitmapFactory.Options定義Bitmap的內容就像它已經存在一樣,這將決定系統是否縮放或者怎樣縮放他們。例如,你可以使用inDensity屬性來給設計好的來指定Bitmap定義密度並且inScaled屬性來指定Bitmap是否縮放來匹配當前設備屏幕密度。

如果你設置inScaled爲false,然後關閉系統將會在draw時期自動縮放的應用於Bitmap的預先縮放功能。

使用自動縮放代替預先縮放會佔用更多CPU但是會佔用更少內存。

圖5展示的是當加載low(120)密度、medium(160)密度和high(240)密度在一個高密度屏幕上預先縮放和自動縮放機制的結果。只有細微的不同因爲所有的Bitmap都是針對當前屏幕縮放的,儘管如此縮放的Bitmap外觀還是會因爲draw時是預先所昂還是自動縮放有細微的不同。


注意:在安卓3.0或者更高,由於圖像框架的改進,預先縮放和自動縮放感覺不出來了。

將dp單位轉化爲px單位

在一些例子中,你需要用dp表示尺寸然後將他們轉爲像素。想想一個程序在用戶的手指在屏幕上滑動或者快速滑動超過16像素就會被記錄下來。在一個基線屏幕上,用戶必須移動160pixels/160dpi等於一英寸(或者2.5mm)的十分之一才能被記錄。在一個高密度(240dpi)設備上,用戶必須移動16pixels/240dpi,等於五分之一英寸(或者1.7mm)。距離非常短程序看上去對於用戶來說是非常靈敏的。

爲了解決這個問題,手勢在代碼中必須用dp表示然後轉化爲實際的像素。例如:

// The gesture threshold expressed in dp,手勢用dp表示
private staticfinalfloatGESTURE_THRESHOLD_DP=16.0f;

// Get the screen'sdensity scale,獲取屏幕密度縮放
final float scale=getResources().getDisplayMetrics().density;
// Convert the dps topixels, based on density scale,基於密度縮放將dp轉爲px
mGestureThreshold = (int)(GESTURE_THRESHOLD_DP* scale+0.5f);

// UsemGestureThreshold as a distance in pixels...使用mGestureThreshold以px爲單位

DisplayMetrics.density屬性指定你必須使用的將dp單位轉爲px的縮放因子,根據當前密度。在一個medium屏幕上DisplayMetrics.density等於1.0;在high-density屏幕上等於1.5;在extra-high-density上等於2.0;在low-density屏幕上等於等於0.75。這個圖是這個因子你應該乘以dp單位根據當前屏幕得到實際的像素。(然後在圖的周圍增加0.5來接近整數,當轉化成一個整數。)更多信息,參考DisplayMetrics類。

不管怎樣,不要給這個事件定義任意的門檻而是應該使用預先縮放對於ViewConfiguration可用的配置值。

使用預先縮放配置值

你可以使用ViewConfiguration類來獲取普通的距離,速度以及安卓系統使用的時間。例如,框架使用的作爲滾動基線的以像素爲單位的距離可以通過getScaledTouchSlop()獲得。

privatestaticfinalint GESTURE_THRESHOLD_DP=ViewConfiguration.get(myContext).getScaledTouchSlop();

ViewConfiguration裏的以getScaled爲前綴的方法保證會返回一個以像素爲單位的值將會在屏幕上很好的展現不管當前屏幕的密度。

如何在多個屏幕測試你的程序

發佈你的程序之前,你應該在它所支持的所有屏幕尺寸和密度上進行測試。安卓sdk包含的模擬器你可以使用,模擬器可以複製常見的屏幕尺寸和密度配置你的應用想運行的。你可以修改複製了任意指定屏幕特徵的模擬器默認的尺寸,密度,分辨率。使用模擬器和附加的定製的配置允許你測試任何可能的屏幕配置,所以你不需要買各種屏幕的設備來測試你的應用支持的屏幕。

設置一個環境來測試你的應用的屏幕支持,你應該穿件一系列的AVDs(安卓虛擬設備),使用模擬器皮膚和屏幕配置模擬你的程序想支持的屏幕尺寸和密度。這樣做,你可以使用AVD管理器創建AVDs並且將他們運行在一個圖像界面。

運行安卓SDK管理器,執行SDK Manager.exe從你的安卓SDK目錄(僅限Windows)或者從<sdk>/tools/目錄執行安卓(所有平臺)。圖6展示的是選擇了AVD的AVD管理器,用來測試各種屏幕配置。


表3展示了在安卓SDK可用的各種模擬皮膚,你可以用來模擬最常用的屏幕配置。

更多信息關於創建和使用AVDs來測試你的程序,參看Managing AVDs with AVD Manager.

表3在安卓SDK中各種可用的屏幕配置(加粗顯示的)和其他典型的分辨率

Low density (120), ldpi

Medium density (160), mdpi

High density (240), hdpi

Extra-high-density (320), xhdpi

Smallscreen

QVGA (240x320)

480x640

Normalscreen

WQVGA400 (240x400) 
WQVGA432 (240x432)

HVGA (320x480)

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

640x960

Largescreen

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

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

Extra-Largescreen

1024x600

WXGA (1280x800)
1024x768
1280x768

1536x1152
1920x1152 
1920x1200

2048x1536
2560x1536 
2560x1600

*爲了模擬這個配置,指定一個160的自定義密度當使用WVGA800 or WVGA854創建一個AVD時

**爲了模擬這個配置,指定一個120的自定義密度當使用WVGA800 or WVGA854創建一個AVD時

這個皮膚在安卓3.0可用

看任何給定屏幕配置的活動設備的相對數值,參看Screen Sizes and Densities

我們常常建議在一個設置成近似實際設備的物理尺寸的模擬器測試你的程序。這將比較各種尺寸和屏幕密度變得很容易。這樣做你需要知道你的電腦顯示器的用dpi表示大致密度(例如,30寸戴爾監視器是96dpi)。當你從AVD管理器運行AVD,在運行選項裏你可以給模擬器指定屏幕尺寸和顯示器dpi,如圖7


如果你想在一個現有的屏幕沒有的密度或者分辨率上測試程序,你可以創建一個AVD使用分辨率和密度。當從AVD管理器創建AVD時,指定分辨率來代替選擇已有的分辨率。

如果你運行AVD在命令行模式,你可以用-scale參數指定模擬器縮放。例如:

emulator-avd<avd_name>-scale96dpi

改善模擬器的尺寸,你可以用-scale加上0.1到3的參數來表示縮放的比率。

更多關於通過命令行創建AVD的信息,參看Managing AVDs from the Command Line.

 

 

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