支援Android系統的手機的種類很多,每種手機的螢幕大小和解析度可能有所不同(螢幕像素密度),Android系統提供了方法在這些有著不同大小,螢幕像素密度的手機上自動調整顯示介面的布局和大小,同時Android也提供了相關API允許開發人員針對不同的螢幕大小和顯示密度來控制UI以便應用在不同配置的裝置螢幕上都有良好的顯示效果。
儘管Android系統提供了螢幕自適應功能可以解決大部分不同螢幕UI顯示的問題,應用還是需要做一些能支援不同螢幕配置的工作,這樣可以給終端使用者在不同螢幕配置下都取的很好的使用者體驗。
在介紹本例之前,先解釋一些術語:
螢幕大小(Screen Size): 裝置螢幕的物理尺寸(對角線長度),比如3寸屏,4寸屏。為簡單起見,Android將螢幕大小分成四類: small (小尺寸), normal(正常尺寸), large(大尺寸), extra large(超大尺寸)。
螢幕顯示密度(Screen Density): 單位尺寸顯示的像素數目。通常採用dpi 為單位( 點數/英寸)。比如“高密度“的螢幕在單位尺寸內顯示的像素數目大於”低密度“的螢幕。為簡單起見,Android也將螢幕顯示密度(後面簡稱螢幕密度或密度)分為low(低密度), medium(中等密度),high (高密度), extra high(超高密度)。
螢幕縱橫方向(Orientation): 從使用者角度看,顯示螢幕可以為橫向(landscape)或是縱向(portrait) ,使用者在應用運行時可以改變螢幕的縱向或是橫向。
螢幕解析度(Resolution): 螢幕支援顯示的像素總數。在談支援多種螢幕配置上,應用通常不之間操作螢幕的解析度,而是要關心螢幕的大小和密度。
密度無關像素(Density-independent pixel– dp) : 在定義Layout是使用到的與裝置無關虛擬像素單位。dp 定義為 160dpi 螢幕上一個像素大小。 160dpi 被Android系統認為是“中等密度”的螢幕。使用dp為單位時,當應用運行時,Android會自動根據螢幕實際的大小和密度放大或是縮小Layout中的控制項達到介面螢幕自適應的效果。 有 dp 值到實際像素值的換算很簡單: px = dp * (dpi /160) 。
Android支援的螢幕範圍 Android系統從1.6開始可以支援多個螢幕大小和螢幕密度,上面說過Android將螢幕大小和螢幕定義都分為四類,採用第一代Android手機T-Mobile G1的螢幕(HVGA)做為基準。顯示了螢幕大小和螢幕定義的一個粗略分類:
應用可以通過提供備選資源的方法來支援不同的螢幕配置。典型的做法是為不同螢幕大小或螢幕密度提供不同的的Layout和圖片資源。Andorid系統運行時可根據當前螢幕的實際配置來選擇合適的Layout和資源顯示使用者介面,通常並不需要為每個螢幕大小和螢幕密度的組合都提供不同的Layout和資源,Android 系統會非常“智能”的來處理不螢幕配置下介面的顯示問題。
螢幕密度無關性(Density independence), 如果說應用具有“螢幕密度無關性”只的是應用的UI組件中不同的螢幕顯示密度小其實際物理尺寸保持不變。
保持介面的實際物理尺寸非常重要,沒有圖,一個按鈕在“低密度”螢幕上的物理尺寸比“高密度”屏上尺寸要大,下面兩幅圖顯示了“不支援螢幕密度無關性”和支援“螢幕密度無關性”的顯示效果:
Android 系統採用下面兩種方法來協助應用實現“密度無關性”:
系統根據當前螢幕密度為採用dp 為單位的Layout 組件自動縮放以適應螢幕。
系統根據當前螢幕密度為Drawable 資源進行縮放。
因此在大部分情況下,可以通過使用dp為單位給Layout中的組件指定大小,和正確使用”wrap_content”屬性來達到“螢幕密度無關性”。但對應bitmap 資源來說,自動的縮放有時會造成放大縮小後的映像變得模糊不清,這是就需要應用為不同螢幕密度配置提供不同的資源:為高密度的螢幕提供高清晰度的映像等。
如何支援多螢幕配置
Android系統本身自動可以支援螢幕自適應,但有時也需要應用提供螢幕配置相關的資源以達到更好的使用者體驗:
為不同螢幕大小提供不同的Layout.
為不同螢幕密度提高不同的bitmap映像資源。
Android系統運行時根據當前螢幕配置選擇合適的Layout和資源,如果對於的螢幕配置沒有提供備選資源,則選用預設資源進行縮放。
下表列出了Android螢幕配置可能的組合:
來看看apidemos中定義的資來源目錄:
比如對於drawable 來說, drawable 不帶任何尾碼,為預設drawable 資源, drawable-hdpi 為高密度螢幕使用的drawable資源, drawable-ldpi 為低密度螢幕使用的drawable 資源等。
同樣values 定義了多種不同配置下使用的資源。
對應不同螢幕密度下的Bitmap資源定義(.png. .jpg, .gif ,.9.png)一個原則上使用 3:4:6:8的比例來為四種不同螢幕密度提供映像資源,比如對於一個“中等密度”下像素大小為48X48的資源,
Low-density: 36X36
Medium-density: 48X48
High-density: 72X72
Extra high-density: 96X96
關於Density的一些額外的考慮
本節內容對於大部分應用不重要,除非你的應用在不同螢幕配置時顯示上出了問題。
為了更好的理解在應用繪製圖形時如何支援不同的螢幕密度配置,你應該知道下面由Android系統提供的一些支援:
Pre-scaling of resources (如bitmap drawable 資源)
Android系統根據當前裝置螢幕配置不進行縮放選取裝置配置相關的資源(比如對於高密度螢幕選取drawable-hdpi目錄下的Drawable資源)。如果沒有找到當前螢幕配置對應的資源,Android使用預設資源(在drawable 目錄下的資源)放大或是縮小以適應螢幕。Android應用認為預設資源(比如drawable 等不帶尾碼的目錄下)是對應於基準螢幕配置(mdpi)的資源。pre-scaling 意思就是Android系統為當前螢幕密度自動縮放Bitmap來適應螢幕的過程。
此時,如果你需要知道這些pre-scaled資源的大小,Android系統返回的是縮放之後的大小,比如對應於mdpi 下50X50像素大小的映像在hdpi螢幕下會放大到75X75像素大小,此時查詢映像大小傳回值為75X75. 如果你不想讓Android對一些資源進行pre-scaling,可以將這些資源放在帶nodpi尾碼的目錄下:比如 /res/drawable-nodpi。
Density 例子中的 no-dpi resource drawable 顯示如下:
像素大小和座標的自動縮放
一個應用也可以通過在Manifest檔案中將android:anyDensity設為”false”或在代碼中將bitmap的isScaled設為false關閉pre-scaling 。在這個情況下,Android系統會自動縮放以pixel為單位的的像素值和座標。結果使得在不同螢幕大小的裝置上仍可以顯示和基準螢幕下類似的物理尺寸大小。這時如果需要返回Bitmap的大小,系統返回的是縮放後的像素值,而非實際物理像素值。
大部分情況“不應該關閉pre-scaling”,而是通過提供螢幕配置相關資源來支援多種螢幕配置。
運行時縮放Bitmap
如果應用在記憶體中動態建立一個Bitmap對應,Android系統會認為這個Bitmap對應於基準螢幕配置(中等密度)。預設情況下,如果在螢幕上顯示這個Bitmap,Android系統會自動縮放以適應當前螢幕。 可以使用setDensity為Bitmap 設定顯示密度。
如果使用BitmapFactory來建立Bitmap對象,可以使用BitmapFactory.Options來定義Bitmap的屬性,如果將inScaled設為false,則會關閉pre-sacling.
為Density例子 顯示 pre-scale 和auto-scale 顯示 low (120), medium (160), high (240) 的映像中高密度屏上顯示的效果:
注意這個例子的Title : Density:High ,可能你的裝置運行時結果不一樣:
[java]
this.setTitle(R.string.density_title);
this.setTitle(R.string.density_title);標題的資源為R.string.density_title ,它在values ,values-large ,values-small中用不同的定義, 在應用運行時,Android系統會根據當前螢幕配置選取合適的資源,你可以多建立幾種不同大小的模擬器,看看結果會有所不同,由此也可以理解本例和Android選取資源的機制。
下表給出模擬器支援的不同螢幕大小和密度的組合:
作者:mapdigit