原文:http://developer.android.com/intl/zh-cn/guide/practices/screens_support.html
翻譯還比較粗糙,有一些地方難免不太通順,而且文檔難免繁瑣和複雜,如果想看精簡一點的移步:http://blog.csdn.net/program_thinker/article/details/41806135
Android運行在各種不同屏幕尺寸和密度的設備上,對於應用程序,Android系統提供了一個一致的跨設備的開發環境並且爲適應不同屏幕處理絕大多數的事情。同時,爲了應對更多特殊的屏幕,系統提供了各種API來優化你的應用程序界面。
雖然系統做了很多的擴展和調整,使你的應用程序能夠在不同的屏幕上工作,但是你也應該做出努力,以優化在不同的屏幕大小和密度設備上的應用程序的表現。在此過程中,你最大程度的爲所有設備增強用戶體驗,讓用戶體驗到你的程序是爲他們設備而作,而不僅僅是拉伸以適應設備屏幕。
按照文檔中描述的行爲,你可以使用一個apk文件創建提供支持所有屏幕配置並且顯示正常的應用程序。
注意:本文檔中信息假定你的應用程序爲Android1.6(API 4)以及更高的版本,如果你的應用程序支持Android1.5或者更低,請寫閱讀Android1.5的策略。
此外,要注意Android3.2引入了新的API,讓你能夠爲支持不同屏幕尺寸更精確控制使用的佈局資源來構建你的應用程序。這些新功能是特別重要的,如果你正在開發對於平板電腦的應用程序,請參閱有關聲明的平板佈局Android3.2部分。
屏幕支持的概述
本節提供了Android多屏幕支持的概述,包括:API介紹,屏幕配置,總結系統使用的術語和概念,以及屏幕底層的概述
術語與概念
實際的物理尺寸,測量屏幕的對角線。
爲簡單起見, Android中的所有實際的屏幕尺寸分爲四個廣義大小:小,正常,大,和超大。
屏幕的物理區域內的像素的數量:通常被稱爲dpi(每英寸點數) 。例如,在給定的物理區域內一個“低”密度屏幕比 “正常”或“高”密度屏幕具有較少的像素。爲簡單起見, Android中的所有實際的屏幕密度分爲六個廣義密度:低,中,高,超高,超超高,超超超高。
從用戶的角度看到的屏幕方向。一般爲橫向或縱向,即屏幕的寬高比。注意,不僅要關注不同的設備在缺省情況下的屏幕方向。同一設備當用戶旋轉時,應用程序的屏幕方向也需要關注。
分辨率
在屏幕上的物理像素的總數。當爲多個屏幕添加了支持,應用程序不直接與分辨率相關:應用程序應只能與屏幕大小和密度有關,和指定的廣義的大小和密度基有關。
密度無關像素(DP)
虛擬像素單元。在定義UI佈局的時候,你應當使用與密度無關的方式來表示佈局尺寸或者位置
密度無關的像素相當於在一個160dpi屏幕上的一個物理像素。這是一個假定在“中等”密度屏幕的基線密度。在運行時候,系統透明的處理任何縮放的DP單位,根據需要轉化成屏幕的實際密度。dp的轉化屏幕實際像素比較簡單:px = dp * (dpi / 160)。例如,一個240dpi的屏幕上,1dp等於1.5的物理像素。定義你的應用程序UI的時候,你應該總是使用dp單位,以確保在不同密度的屏幕UI的正確顯示
屏幕支持的範圍
爲了簡化您設計針對多個屏幕的用戶界面的方法,Android把實際的屏幕尺寸和密度分成如下範圍:
mdpi (中) 〜 160dpi
hdpi(高) 〜 240dpi
xhdpi (超高) 〜 320dpi
xxhdpi (超超高) 〜 480dpi
xxxhdpi (超特超高) 〜 640dpi
- 超大屏幕是至少960dp X 720dp
- 大屏幕至少640dp X 480dp
- 正常屏幕至少470dp X 320dp
- 小屏幕至少426dp X 320dp
你不需要對屏幕尺寸和密度的各種組合提供備選的資源。系統提供了強大的兼容功能,可以處理你的應用程序在大多數設備屏幕上工作,前提是你使用能夠調整的技術(如最佳實踐說明,下同)實現您的UI。
注意:定義一個設備的屏幕尺寸和密度的特性是彼此獨立的。例如,一個WVGA高密度屏幕被認爲是一個正常大小的屏幕,因爲它的物理尺寸和T-Mobile G1大致相同( Android的第一臺設備和基準屏幕) 。另一方面,一個WVGA中密度屏幕被認爲是一個大尺寸屏幕。雖然它提供了相同的分辨率(像素數相同) ,所述的WVGA中密度屏幕具有較低的屏幕密度,這意味着每個像素在物理上是較大的,因此,整個屏幕比基線(正常大小)的屏幕大。
屏幕密度獨立
當你的應用實現了“密度獨立”時,從用戶的角度看,在不同密度屏幕顯示的用戶界面元素都保持了對應的物理尺寸(譯者注:就是用戶看起來不同屏幕體驗都一樣,這話說成這樣真是繞)
維持密度獨立性是很重要的,因爲如果沒有它,一個用戶界面元素(如按鈕)顯示在低密度屏幕上比顯示在高密度屏幕上在物理上更大。這樣的密度有關大小的變化可能會導致你的應用程序的佈局和可用性問題。圖2和3表明應用程序提供或者不提供密度獨立顯示的差異。
圖2:密度不獨立的應用程序,對不同密度屏幕的顯示效果
圖3:密度獨立的應用程序,對不同密度屏幕的顯示效果
Android系統可以幫助您的應用程序實現密度獨立兩種方式:
- 系統爲適合當前屏幕密度伸縮dp單位
- 系統根據當前屏幕密度擴展資源到合適的大小,如果需要的話
從Android 3.2 ( API等級13 )起,上述尺寸組已過時,應改用sw <n > dp配置限定符來定義你的佈局資源所需的最小可用寬度。例如,如果你的平板電腦的佈局至少需要600dp屏幕寬度,你應該把它放在文件夾layout-sw600dp /下 。在有關平板佈局的聲明在Android 3.2節進一步討論。
- <resources_name>是標準的資源名稱(例如drawable或者layout)。
- <qualifier>是表1的結構限定符。指定這些資源將被哪種屏幕配置使用(比如hdpi和xlarge)。
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/my_icon.png // bitmap for medium-density res/drawable-hdpi/my_icon.png // bitmap for high-density res/drawable-xhdpi/my_icon.png // bitmap for extra-high-density res/drawable-xxhdpi/my_icon.png // bitmap for extra-extra-high-density請注意,當Android系統選擇將哪些資源在運行時使用時,它使用一定的邏輯來決定“最佳匹配”的資源。也就是說,你的限定符可以不必在所有情況下都匹配當前的屏幕配置。具體地,如果基於當前尺寸沒有資源限定符很好的匹配的時候,系統會選擇使用比當前屏幕小的資源(例如,如果必要的話,一個大尺寸屏幕會使用普通大小的屏幕資源) 。然而,如果唯一可用的資源比當前的大,如果沒有其他的資源相匹配的設備配置,系統將不會使用它們(例如,如果所有的資源佈局都標記XLARGE限定符,但設備是一個正常大小的屏幕),應用程序會崩潰。有關係統如何選擇資源的更多信息,請閱讀安卓如何查找最佳匹配資源(http://developer.android.com/guide/topics/resources/providing-resources.html#BestMatch)。
以下各節分別概述了你可能想使用的大小和密度限定符創建備選佈局和繪圖資源。
- 當在小屏幕上進行測試時,你可能會發現,你的佈局並不完全適合在該屏幕上。例如,一排按鈕未必適合在一個小屏幕設備上的寬度內。在這種情況下,你應該爲小屏幕的替代佈局調整按鈕的大小或位置。
- 當在一個特大屏幕上進行測試時,你可能會意識到你的佈局不能有效地利用大屏幕,並且界面元素明顯拉長以填補它。在這種情況下,你應該有針對性地重新設計一個超大屏幕的替代佈局。雖然你的應用程序在不使用大屏幕替代佈局的時候也應該正常工作,但在用戶看來,你的應用程序看起來好像是爲他們的設備專門設計是非常重要的。如果UI明顯拉長,用戶的應用體驗更可能是不滿意的。
- 並且,與縱向測試相比,橫向的時候,你可能會注意到,放置在縱向屏幕底部的UI元素應該放置在橫向屏幕的右側
- 適合在小屏幕上(這樣用戶可以實際使用應用程序)
- 對於更大的屏幕優化,充分利用額外的屏幕空間的優勢
- 優化橫向和縱向兩個方向
- 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
- 180x180 (3.0x) for extra-extra-high-density
- 192x192 (4.0x) for extra-extra-extra-high-density (launcher icon only; see note above)
- 320dp: 一款典型的手機屏幕 (240x320 ldpi, 320x480 mdpi, 480x800 hdpi, etc).
- 480dp: 一般的平板 (480x800 mdpi).
- 600dp: 7” 平板 (600x1024 mdpi).
- 720dp: 10” 平板 (720x1280 mdpi, 800x1280 mdpi, etc).
res/layout/main_activity.xml # 對手機 res/layout-sw600dp/main_activity.xml # 對平板在這種情況下,對於使用平板佈局所需的最小寬度必須是600dp。
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)注意,以上兩套資源示例使用的都是“最小寬度”限定符, sw <N >dp ,其中規定了兩個方向的最小屏幕,無論設備當前處在什麼方位。因此,使用sw<N >dp是忽略屏幕的方向指定整體屏幕尺寸可供佈局的簡單方法。
- 在XML佈局文件中指導尺寸時,使用wrap_content,fill_parent或者dp單位
- 不要在你的應用程序代碼中使用硬編碼的像素值
- 不要使用AbsoluteLayout(不建議使用)
- 提供備用的位圖來繪製不同屏幕密度的圖像
以下爲更詳細的說明
例如,對於一個layout_width=“100dp”的圖,在中密度屏幕上佔據100像素寬度而在高密度屏幕上擴展到150個像素,以使圖在屏幕上佔據大致相同的物理空間
同樣的,你應該使用sp來定義文字的大小,這個sp比例因子依賴於用戶設定,系統將擴展它爲dp大小。
2、不要在你的應用程序代碼中使用硬編碼的像素值
出於性能的考慮,併爲了保持代碼簡單,Android系統使用像素值作爲表達維度或者座標的標準單位。這意味着,一個視圖的尺寸在代碼中始終是用像素表示的,但這是根據當前屏幕的像素密度。例如,如果myView.getWidth()返回是10,那麼認爲是在當前屏幕上的10個像素,如果在具有較高密度屏幕的設備上,這個返回值可能是15。如果你應用程序代碼使用像素值來處理沒有縮放適配當前屏幕的位圖,那麼你可能需要在代碼中縮放位圖資源的像素值來適配當前屏幕。
3、不要使用AbsoluteLayout
不像其他的窗口布局小部件,AbsoluteLayout強制使用固定的位置來佈置其子視圖,這很容易導致用戶界面在不同的屏幕上無法很好工作,因此AbsoluteLayout在Android1.5(API 3)已經過時。
你應該使用RelativeLayout,它對子視圖使用相對的位置,例如你可以指定一個按鈕控件出現在一個文本小部件的右邊(“to the right of”)
4、使用大小和密度特定的資源
雖然系統可以根據當前屏幕配置的繪製資源擴展你的佈局。但你仍然要爲不同的屏幕尺寸的用戶界面,提供不同密度優化的位圖資源。這基本上是重申了本文檔早期的信息
如果你需要精確的控制你的應用程序在不同屏幕配置的佈局,調整特定資源目錄中的佈局和位圖,例如,假設你要顯示中,高密度的屏幕圖標,簡單的創建兩個不同大小的圖標(例如100x100中密度和150x150高密度),並放在適當的目錄中,使用適當的限定符:
res/drawable-mdpi/icon.png //for medium-density screens res/drawable-hdpi/icon.png //for high-density screens注意:如果在目錄名中沒有定義密度限定符,那麼系統將假定該目錄中的資源是爲中密度基線所準備的並會將其擴展以適應其他的密度
附加的密度注意事項
本節將介紹更多關於Android系統如何在不同屏幕上擴展位圖資源和你如何在不同的像素密度上更進一步的控制位圖的繪製。本節的信息,對於大多數應用程序不是非常重要,除非你在不同屏幕密度下運行或者你的應用程序在操作圖形的時候遇到問題。
爲了更好的理解怎麼能夠在運行操作圖形時支持多種密度,你應該明白系統如何通過以下方式確保位圖適當的伸縮
1、預縮放資源(比如位圖資源)
基於當前的屏幕密度,系統使用你應用程序的任何大小或者特定密度的資源不進行縮放的顯示它們。如果資源在當前密度不可用時,系統會加載默認資源並且根據匹配當前密度的需求適當縮放它們。系統假設默認資源(沒有配置限定符文件夾下的)是專爲基準屏幕像素密度而準備,除非他們從有特定密度相關的資源目錄下加載。預縮放就是系統重新調整位圖的大小從而適應當前的屏幕。
如果你請求預縮放資源的尺寸,系統會返回縮放後的尺寸值。例如,在mdpi上設計的一個50x50do的位圖在hdpi的屏幕上會被縮放到75x75dp(如果沒有應用與hdpi的備選資源)
有些情況下,你可能不希望Android預縮放資源。避免預縮放資源的方法很簡單,就是創建使用nodpi爲限定符的資源目錄,如下所示
res/drawable-nodpi/icon.png當系統使用該目錄下的位圖時,系統不會基於當前屏幕像素密度縮放它。
2、自動縮放尺寸和座標
應用可以在manifest文件中設置android:anyDensity="false"來禁止使用預縮放,或者編碼設置位圖資源的屬性“isScaled”禁用預縮放。在這種情況下,系統在繪圖時會自動縮放任意絕對像素座標和像素尺寸值。這樣做是爲了確保像素定義的屏幕元素顯示合適的物理尺寸。系統爲應用程序透明的處理這個縮放並且報告縮放的像素尺寸給應用程序,而不是物理像素尺寸。
例如,假如一臺設備具有一個480x480dp的WVGA高密度屏幕同時尺寸和傳統的HVGA屏幕相同。運行的應用程序禁止了預縮放功能,在這種情況下,當查詢屏幕尺寸的時候系統會依據應用,並報告320x533(近似mdpi的屏幕密度),當應用程序進行繪製操作的時候,比如畫一個從(10,10)到(100,100)的長方形時,系統會根據合適的量縮放座標,可能實際畫的區域是從(15,15)到(150,150)。如果你的應用程序直接操作縮放位圖,這種差異可能導致意外的行爲。但是爲了保持應用程序更好的表現,這被認爲是一個合理的權衡。
通常情況下,你不應該禁用預縮放。支持多屏的最好方法是遵循上訴的基本技術。
如果你的應用程序操作位圖或者以其他的方式與屏幕上的像素直接進行交互,你可能需要採取更多的措施來支持不同屏幕密度。例如,如果你通過手勢計算手指穿過的像素數量,你需要使用密度獨立的虛擬像素而不是實際像素值。
運行時縮放位圖對象
如果你的應用程序創建了一個內存中的位圖(一個bitmap對象)時,系統假設這個位圖是爲中密度的屏幕設計的。默認情況下,繪製的時候自動縮放這個位圖。當位圖沒有特殊的密度特性時,系統對位圖提供自動縮放。當你沒有正確考慮設備的屏幕密度和指定位圖的密度特性,自動縮放可能導致不好的效果當你不提供可替代的資源。
要控制運行時創建的位圖是否縮放, 你可以使用setDensity()函數指定位圖的密度,從DisplayMetrics傳遞一個密度,比如DENSITY_HIGH或DENSITY_LOW
如果你使用BitmapFactory(比如文件或者流)來創建位圖,你可以使用BitmapFactory.Options來定義位圖的屬性,這可以確定是否和如何讓系統縮放它。例如,你可以使用inDensity字段來位圖的密度是否被設計和inScaled字段來指定位圖是否應該縮放以匹配當前設備的屏幕密度。
如果你設置inScaled字段是false,那麼你禁用任何縮放,系統將會自動縮放,使用自動縮放比預縮放可能更耗CPU,但使用較少內存。
圖5:預縮放和自動縮放的位圖比較
圖5表明在高密度屏幕上加載低(120dp),中(160dp),高(240dp)密度的位圖時預縮放和自動縮放的結果,差異是微小的,因爲所有的位圖都被縮放以匹配的當前的屏幕密度,但是略有不同的外觀,這取決於是否是預縮放或者自動縮放的。
注意: 在Android3.0及以上,由於圖形框架的改善,預縮放和自動縮放位圖之間沒有明顯差異。
轉化dp單位到px單位
在某些情況下,你將需要的dp尺寸轉化爲像素尺寸。想象一個滾動或者手勢滑動應用,用戶手指必須移動至少16個像素才能被識別,在基準屏幕上,一個用戶必須移動16px/160dpi,等於1/10英寸(2.5毫米)纔會被識別。而在一個高密度設備上(240dpi),用戶只需要移動16px/240dpi,相當於1/15英寸(1.7毫米)就可以被識別,移動距離更短,應用程序應該對用戶手勢表現的更敏感。
要解決這個問題,手勢識別必須使用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...
根據當前屏幕密度,你必須指定DisplayMetrics.density字段作爲dp單位轉化爲px單位的比例因子。在中等密度的屏幕,DisplayMetrics.density等於1.0;高密度等於1.5;超高密度的比例因子爲2.0;在低密度時,它等於0.75.你的當前dp值必須成語這個數字才能得到當前屏幕的實際像素值(添加0.5f然後將其轉換爲最接近的整數)。有關的詳細信息,請參閱DisplayMetrics這個類。
使用預縮放的配置值
你可以使用ViewConfiguration這個類去訪問通常的距離,速度和Android系統的時間。例如,框架所使用的滾動閾值的像素距離可以用getScaledTouchSlop()函數獲得:
private static final int GESTURE_THRESHOLD_DP = ViewConfiguration.get(myContext).getScaledTouchSlop();
如何測試你的應用在多個屏幕上的表現
在發佈你的應用程序之前,你應該徹底在它所有支持的屏幕密度和尺寸的設備上測試。Android SDK中包含了你可以使用的模擬器,它是複製了常見的密度和尺寸大小的仿真樣式機,你也可以調整模擬器的尺寸和密度。所以你可以通過使用模擬器而不必爲了你的應用程序屏幕支持而購買各種設備。
圖6:一套爲測試屏幕支持的模擬機
要創建測試你的應用程序的屏幕支持的環境,你必須創建一系列模擬機(Android虛擬設備)。模仿出你喜歡你的應用程序支持的屏幕大小和密度。要做到這點,你可以使用AVD管理器創建他們。
爲運行Android SDK管理器,打開你Android SDK目錄下的執行文件manage.exe(僅在Windows上),或者從<sdk>/tools/directory(所有平臺)執行android。圖6顯示了AVD管理一系列的AVDs
表3顯示了Android SDK顯示的各種仿真機型,你可以用它來模擬一些常見的屏幕配置。
有關創建和使用AVD來測試您的應用程序,更多信息請看http://developer.android.com/tools/devices/managing-avds.html
表3:Android SDK中各種屏幕配置模擬器
我們還建議你設置緊密匹配你實際設備物理尺寸的模擬器來運行你的程序,這讓它的測試結果更加可靠。爲了做到這點,你必須知道你的電腦顯示器的大致的密度(dpi),比如,一個30“戴爾顯示器擁有96dpi的密度。當你從AVD管理器啓動一個AVD,你可以指定模擬機的屏幕,並啓動顯示器DPI選項,如圖7
圖7:啓動AVD時設置大小和密度
當你的想測試的屏幕尺寸或者密度內置的機型不支持,你可以創建一個自定義分辨率或者密度的AVD,當你從AVD管理器中創建AVD時候,指定而不是選擇一個分辨率(或者密度)。
如果你用命令行啓動AVD,你可以使用-scale選項來指定模擬器的scale。例如:
emulator -avd <avd_name> -scale 96dpi
有關通過命令行創建AVD的更多信息,請參閱http://developer.android.com/tools/devices/managing-avds-cmdline.html
OVER
啃下來真是累。。。廢話太多準備總結一下出點乾貨
還有英文有限,翻譯的不好的地方請大家指正