android螢幕適配詳解

舉個例子發表於2015-09-02

官方地址:http://developer.android.com/guide/practices/screens_support.html

 

一、關於佈局適配建議

1、不要使用絕對佈局
2、儘量使用match_parent 而不是fill_parent 。
3、能夠使用權重的地方儘量使用權重(android:layout_weight)
4、如果是純色背景,儘量使用android的shape 自定義。
5、如果需要在特定解析度下適配,可以在res目錄上新建layout-HxW.xml的資料夾。比如要適配 1080*1800的螢幕(魅族MX3採用此解析度)則新建layout-1800x1080.xml的資料夾,然後在下面定義佈局。Android系統 會優先查詢解析度相同的佈局,如果不存在則換使用預設的layout下的佈局。
 

二、術語和概念

四種螢幕尺寸分類:: small, normal, large, and xlarge
四種密度分類: ldpi (low), mdpi (medium), hdpi (high), and xhdpi (extra high)
需要注意的是: xhdpi是從 Android 2.2 (API Level 8)才開始增加的分類.
xlarge是從Android 2.3 (API Level 9)才開始增加的分類.
DPI是“dot per inch”的縮寫,每英寸畫素數。

一般情況下的普通螢幕:ldpi是120,mdpi是160,hdpi是240,xhdpi是320。

 

三、如何做到自適應螢幕大小呢?

1)介面佈局方面

   需要根據物理尺寸的大小準備5套佈局,layout(放一些通用佈局xml檔案,比如介面中頂部和底部的佈局,不會隨著螢幕大小變化,類似windos窗 口的title bar),layout-small(螢幕尺寸小於3英寸左右的佈局),layout-normal(螢幕尺寸小於4.5英寸左右),layout- large(4英寸-7英寸之間),layout-xlarge(7-10英寸之間)

2)圖片資源方面

  需要根據dpi值準備5套圖片資源,drawable,drawalbe-ldpi,drawable-mdpi,drawable-hdpi,drawable-xhdpi

Android有個自動匹配機制去選擇對應的佈局和圖片資源

 

四、兩種獲取螢幕解析度資訊的方法:

DisplayMetrics metrics = new DisplayMetrics();
Display display = activity.getWindowManager().getDefaultDisplay();
display.getMetrics(metrics);
//這裡得到的畫素值是裝置獨立畫素dp

//DisplayMetrics metrics=activity.getResources().getDisplayMetrics(); 這樣獲得的引數資訊不正確,不要使用這種方式。
不能使用android.content.res.Resources.getSystem().getDisplayMetrics()。這個得到的寬和高是空的。

 

五、關於圖片製作

1)關於設計:
設計圖先定下一個要設計的尺寸,而且儘量採用在目前最流行的螢幕尺寸(比如目前佔螢幕比重比較多的是480系列,也即是480*800或者400*854,下面的圖示製作也在次基礎上進行比例的換算)上設計。
先了解一下螢幕的級別:
螢幕級別
螢幕密度
比率(相對)
物理大小(英寸)
畫素大小
通常的解析度
ldpi
120
3
0.75
1
120
 
mdpi
160
4
1
1
160
320*480
hdpi
240
6
1.5
1
240
480*800
xhdpi
320
8
2
1
320
720*1280
xxhdpi
480
12
3
1
480
1080*1800
說明:
螢幕級別:
注意螢幕級別是按照密度分級,和畫素沒有關係。如果非要讓密度和畫素扯上關係,則需要一個參照系,android使 用mdpi級別作為標準參照螢幕,也就是說在320*480解析度的手機上一個密度可以容納一個畫素。然後其他密度級別則在此基礎上進行對比。如果理想情 況下,480*800的螢幕一個密度可以容納1.5個畫素。
物理大小:
單位是英寸而不是畫素,也就說一個英寸在任何解析度下顯示的大小都是一樣的,但是畫素在密度不同的手機裡面顯示的實際的大小是不一樣的(這就是為什麼android手機需要適配的原因)。
然後就是重點。
假設1畫素在160密度下顯示1英寸,則1畫素在240密度基礎上顯示大約0.67英寸,在320密度下顯示0.5英寸。於是就出現一種情況,在電腦上的一個畫素,在不同的手機上看實際的大小不一樣。那麼怎麼讓“設計效果”在不同的手機上看起來顯示的區域一樣呢?
還是假設一個畫素在160密度下的顯示在一個密度內,也假設就是一英寸。那麼需要幾個畫素才能在240密度級別下顯示在一英寸範圍內呢?答案是1.5個畫素(根據上圖的比率換算)。
瞭解了這個關係,接下來就是圖示的製作。
2)關於切圖。
關於切圖有幾個建議:
第一,長寬最好是3的倍數(根據android的推薦logo圖示的大小是48(mdpi),72(hdpi),96(xhdpi)得出的最小公約數)。
第二,長寬最好是偶數。因為奇數在進行等比壓縮的時候可能有問題。
第三,根據上面兩條,如果長寬是6的倍數最理想。
第四,如果可以拉伸而不改變設計意圖的情況下,比如純色背景,則使用android的9path工具製作成.9的圖片。
3)關於圖示的適配。
然後接下來的一切就和設計稿沒什麼關係。在切好圖的基礎上,根據螢幕密度、畫素和實際大小的比例關係。假如設計司在 480*800的解析度下做好了設計圖,並且切好圖,如果你需要適配720*1280螢幕,該怎麼做?根據比例,他們的關係是2:3,於是你需要按照 1.5倍比例製作圖示,比如你在480*800的設計稿上切下來一個20*20畫素的圖,那麼你就需要製作一個等比放大成30*30畫素的圖示,這樣同一 個圖示在480*800的螢幕和720*1280的螢幕上顯示的實際大小才一樣。同理,如果你需要適配xxhdpi則需要在20*20的基礎上製作一個等 比放大成40*40畫素的圖示。
4)關於圖示的目錄,480*800切下來的圖我們放在drawable-hdpi目錄下,按照2:3放大的圖示放在drawable-xhdpi目錄下,按照2倍放大的圖示放在drawable-xxhdpi目錄下。
android會根據手機的密度優先查詢對應的目錄的資源,
比如408*800解析度下的手機如果密度是160,則自動載入drawable-hdpi這個目錄下的圖示,
如果720*1280密度是240的手機自動載入drawable-xhdpi這個目錄下的圖示。如果沒有這個資料夾,則查詢和240最接近的對應密度資料夾。
5)其它
接下來要說的估計會讓你失望,根據上面的步驟也不能完全解決適配的問題,只能是大概適配,而就算根據上面的步驟大概適配了,實際在手機上的效果也有出入。
比如魅族MX3的解析度是1080*1800,標準情況下密度是480,但是他的密度大約是524,和480接近, 也就是會查詢drawable-xxhdpi這個資源下的檔案。也就是說你在480*800解析度下切圖然後按兩倍放大的圖示在這臺手機上顯示的效果還是 比實際的小。
而另一個要說的問題是540*960或者640*960,他們的密度很可能是或者接近240也可能是320。於是在480*800的設計稿上切下來的圖並且進行的適配製作,在這些手機上顯示的實際大小也可能或大或小。
綜上所述,我也只是把我的理解和經驗分享一下,但是並不能完美適配螢幕,僅僅當做拋磚引玉,如果您路過並且看到這份建議,如果你正好有更好的方案能夠進行適配,請不吝賜教。
 
在程式碼中獲取螢幕畫素、螢幕密度 
DisplayMetrics metric = new DisplayMetrics(); 
getWindowManager().getDefaultDisplay().getMetrics(metric); 
int width = metric.widthPixels; // 螢幕寬度(畫素) 
int height = metric.heightPixels; // 螢幕高度(畫素) 
float density = metric.density; // 螢幕密度(0.75 / 1.0 / 1.5) 
int densityDpi = metric.densityDpi; // 螢幕密度DPI(120 / 160 / 240) 
 

DPI是“dot per inch”的縮寫,每英寸畫素數。
一般情況下的普通螢幕:ldpi是120,mdpi是160,hdpi是240,xhdpi是320。
參考:http://developer.android.com/images/screens_support/screens-ranges.png

 

附加:配置限定符名稱

配置 限定符值 說明
MCC和MNC 例如:
mcc310
mcc310-mnc004
mcc208-mnc00
MCC是移動國家程式碼的英文首字母縮寫(The mobile country code),它的後面可選擇性的跟隨來自裝置內的SIM卡的行動網路程式碼(MNC:mobile network code)。如在任何載體上,mcc310代表美國,mcc310-mnc004代表美國的Venizon公司,mcc208-mnc00代表法國的 Orange公司。
如果裝置使用音訊連線(GSM 電話),那麼MCC和MNC的值來自SIM卡。
也可以單獨使用MCC(例如,在應用程式中包含特殊國家合法的資源)。如果僅需要指定語言環境,那麼可以使用language和region限定符來替代(稍後討論)。如果決定要使用MCC和MNC限定符,就要仔細測試,使它能夠滿足你所期望的工作。
還可以檢視配置域mcc和mnc,它們分別指示了當前的移動國家程式碼和行動網路程式碼。
mcc:http://developer.android.com/reference/android/content/res/Configuration.html#mcc
mnc:http://developer.android.com/reference/android/content/res/Configuration.html#mnc
 
語言和地區 例如:
en
fr
en-rUS
fr-rFR
fr-rCA
語言是用兩個字母的ISO 639-1語言程式碼定義的,緊跟其後的是可選的兩個ISO-3166-1-appha-2地區程式碼字母(前面是小寫的“r”)。
這個編碼不區分大小寫,r字首被用於區分地區部分,不能夠單獨指定地區。
如果使用者改變了系統中的語言設定,那麼在應用程式的執行期間也能夠改變為對應的語言。
最小寬度 sw<N>dp
例如:
sw320dp
sw600dp
sw720dp
螢幕的基本尺寸,是指最短的可用螢幕區域。具體的說,裝置的最小寬度是螢幕可用的寬度和高度中最短的那個(也可以把它看做是螢幕的最小可能的寬度)。這樣就可以使用這個限定符來確保應用程式至少有<N>dp的寬度可用於UI介面,而不管螢幕的當前方向。
例 如,如果佈局在任何時候都需要至少600dp的最小螢幕尺寸,那麼就能夠使用這個限定符,在res/layout-sw600dp/目錄中建立佈局資源。 系統只會在可用螢幕的尺寸至少是600dp的時候才會使用這些資源,而不管600dp是否是被使用者認知的高度或寬度。最小寬度是裝置的固定螢幕尺寸特徵, 當螢幕的方向發生改變時,裝置的最小寬度不改變。
裝置的最小寬度需要考慮螢幕的裝飾和系統UI的佔用。例如,如果裝置有一些固定的UI元素要沿著 最小寬度的軸向,佔用一定的螢幕空間,那麼系統宣告的最小寬度要比實際的螢幕尺寸要小,因為被系統佔用的畫素部分對使用者應用程式的UI無效。因此,這個值 應該是應用程式佈局所需要的最小的實際尺寸(通常,這個值是佈局支援的最小寬度,而不管螢幕的當前方向)。
以下是可以使用的通用螢幕尺寸的一些值:
1.320,針對以下螢幕配置的裝置:
  240x320ldpi(QVGA手持裝置)
  320x480mdpi(手持裝置)
  480x800hdpi(高解析度手持裝置)
2.480,針對480x800mdpi的螢幕(平板或手持裝置)
3.600,針對600x1024mdip的螢幕(7英寸平板)
4.720,針對720x1280mdip的螢幕(10英寸平板)
當應用程式提供了多個帶有不同值的最小寬度限定符資源目錄時,系統會使用最接近(不超出)裝置最小寬度的那個資源。
這個限定符被新增在API級別13中。
還要看android:requiresSmallestWidthDp屬性,它宣告瞭與你的應用程式相容的最小的最小寬度,並且smallestScreenWidthDp配置欄位會持有這個裝置最小寬度的值。
可用寬度 w<N>dp
例如:
w720dp
w1024dp
指定最小的可用螢幕寬度,在資源中應該以dp為單位來定義<N>的值。當方向在橫向和縱向之間改變時,這個配置值會跟當前的實際的寬度相匹配。
當 應用程式給這個配置提供了多個不同值的資源目錄時,系統會使用最接近(不超過)裝置當前螢幕寬度的那個配置。這個值需要考慮螢幕裝飾佔據的空間,因此,如 果裝置在顯示的左邊或右邊有一些固定的UI元素,那麼使用的寬度值就要比實際的螢幕尺寸小,因為這些固定UI元素的佔用,使得應用程式的可用空間減少。
這個特性被新增在API級別13中
還要看screenWidthDp配置欄位,它持有當前的螢幕寬度。
可用高度 h<N>dp
例如:
h720dp
h1024dp
指定最小的可用螢幕高度,在資源中應該以dp為單位來定義<N>的值,當方向在橫向和縱向直接改變時,這個配置值應該跟當前的實際高度匹配。
當 應用程式給這個配置提供了不同值的多個資源目錄時,系統會使用最接近(不超過)裝置當前螢幕高度的那個配置。這個要考慮螢幕裝飾的佔用情況,因此,如果設 備在顯示的上方或底部有一些固定的UI元素,那麼要使用的高度值要比實際的螢幕尺寸小,因為這些固定UI元素的佔用,使得應用程式的可用空間減少。不固定 的螢幕裝飾(如電話的狀態列能夠在全屏時被隱藏)是不考慮的,像標題欄或操作欄這樣的視窗裝飾也不考慮,因此應用必須準備處理比它們指定的空間要小的情 況。
這個限定符被新增在API級別13中。
還要看screenHeightDp配置欄位,它持有當前螢幕的高度。
螢幕尺寸 small
normal
large
xlarge
small:這種屏類似低解析度的QVGA螢幕。對於小屏的最小布局尺寸大約是320x426dp。例如QVGA低解析度和VGA高解析度。
normal:這種屏類似中等解析度的HVGA螢幕。對於普通螢幕的最小布局尺寸大約是320x470dp。如,WQVGA低解析度屏、HVGA中等解析度屏、WVGA高解析度屏。
large:這種屏類似中等解析度的VGA螢幕,對於大螢幕的最小布局尺寸大約是480x640dp。例如VGA和WVGA的中等解析度屏。
xlarge:這種屏被認為比傳統的中等解析度的HVGA螢幕大。針對xlarge屏的最小布局尺寸大約是720x960dp。在大多數情況下,這種超大螢幕的裝置因為太大而要放到揹包中來攜帶,而且最有可能的是平板樣式的裝置。
注意:使用尺寸限定符不意味著資源僅用於這個尺寸的螢幕。如果沒有用限定符提供與當前裝置配置相匹配的可選資源,那麼系統會使用與配置最接近的資源。
警告:如果所有使用尺寸限定符的資源都比當前螢幕大,那麼系統將不會使用它們,並且應用程式會在執行時崩潰(例如,如果所有的佈局都被標記了xlarge限定符,而裝置卻是一個普通尺寸的螢幕)。
這個限定符被新增在API級別4以後的版本中。
螢幕外觀 long
notlong
long:長螢幕,如WQVGA、WVGA、FWVGA
notlong:非長螢幕,如QVGA、HVGA、VGA
這個限定符被新增在API級別4以後的版本中
這個限定符完全是基於螢幕的外觀比率,不相對螢幕的方向。
還要看screenLayout配置欄位,它指示了螢幕是否是長屏。
螢幕方向 port
land
port:縱向裝置(垂直)
land:橫向裝置(水平)
如果使用者旋轉螢幕,這個限定能夠在應用程式執行期間改變。
orientation配置欄位指示當前裝置的方向。
泊位模式 car
desk
car:裝置停靠在汽車中
desk:裝置停靠在書桌中
這個限定符被新增在API級別8以後的版本中
如果使用者改變了裝置的停靠地點,那麼能夠在應用程式的執行期間改變這個限定。可以使用UiModeManager物件來啟用或禁止這種模式。
夜間模式 night
notnight
night:夜間
notnight:白天
被新增在API級別8以後的版本中
如果夜間模式被保留在自動模式中(預設),那麼在應用程式執行期間,會基於白天的時間來進行模式的改變。可以使用UiModeManager物件來啟用或禁止這種模式。
螢幕畫素密度(dpi) ldpi
mdpi
hdpi
xhdpi
nodpi
tvdpi
ldpi:針對大約120dpi的低解析度螢幕;
mdpi:針對大約160dpi的中等解析度螢幕(在傳統的HVGA上);
hdpi:針對大約240dpi的高解析度螢幕;
xhdpi:針對大約320dpi的超高解析度螢幕,被新增在API基本8以後的版本中;
nodpi:這個限定被用於不想根據匹配的裝置解析度進行縮放的點陣圖資源。
tvdpi: 在mdpi和hdpi之間的螢幕,大約是213dpi。這種分組不是主要的解析度,大多數是為電視來考慮的,並且大多數應用不需要它---提供mdpi和 hdpi資源就可以滿足大多數應用程式需要了,並且系統會適當的縮放它們。這個限定符在API級別13以後被引入。
四種主要的解析度之間的縮放比例是:3:4:6:8(忽略tvdpi解析度),因此一個9x9的ldpi點陣圖,在mdpi中是12x12、在hdpi中是18x18、在xhdpi中是24x24。
如果感覺在電視或其他某些裝置上的圖片資源不好看,並且想要試用tvdpi資源,那麼縮放因子是1.33*mdpi。例如,一個100px x 100px的mdpi圖片的圖片應該被放大成133px x 133px的tvdpi圖片。
注意:使用解析度限定符不意味著資源僅適用與對應解析度的螢幕。如果沒有提供與當前裝置配置匹配的可選資源,那麼系統會使用最接近的資源。
觸屏型別 notouch
stylus
finger
notouch:非觸屏裝置
stylus:有適用手寫筆的電阻屏裝置
finger:觸屏裝置
touchscreen配置欄位,指示到了裝置上的觸屏型別。
鍵盤可用性 keysexposed
keyshidden
keyssoft
keysexposed:裝置有可用的鍵盤。如果裝置啟用了軟鍵盤,那麼即使在硬鍵盤沒有暴露給使用者時也可以使用這個限定符。如果沒有提供軟鍵盤或者軟鍵盤被禁用,那麼只有在硬鍵盤被暴露給使用者時才能夠使用這個限定符。
keyshidden:裝置有可用的硬鍵盤,但是被隱藏了,並且裝置沒有可用的軟鍵盤。
keyssoft:裝置有可用的軟鍵盤,不管它是否可見。
如果提供了keysexposed資源,但沒有keyssoft資源,那麼只要系統有可用的軟鍵盤,系統就會使用keysexposed資源而不管鍵盤是否可見。
如果使用者開啟了硬鍵盤,就可以在應用程式執行期間改變這個限定。
hardKeyboardHidden和keyboardHidden配置欄位分別指明硬鍵盤的可見性以及可見的鍵盤型別(包括軟鍵盤)。
主要文字輸入法 nokeys
qwerty
l2key
nokeys:裝置沒有用於文字輸入的硬鍵盤;
qwerty:裝置有標準的硬鍵盤,不管使用者是否可見;
12key:裝置有12個鍵的硬鍵盤,不管使用者是否可見。
keyboard配置欄位指明可用的主要文字輸入方法。
導航鍵的有效性 navexposed
navhidden
navexposed:導航鍵對使用者可用;
navhidden:導航鍵不可用。
如果使用者能夠看到導航鍵,那麼在應用程式執行時就能夠改變這個限定。
navigationHidden配置欄位,指示導航鍵是否隱藏。
主要的非觸屏導航方法 nonav
dpad
trackball
wheel
nonav:除了使用觸屏以外,裝置沒有其他導航設施。
dpad:裝置有用於導航的定向板(d-pad)。
trackball:裝置有用於導航的軌跡球。
wheel:裝置有用於導航的定向滾輪(不常見)。
navigation配置欄位指明可用的導航方法型別。
平臺版本(API 級別) 例如:
v3
v4
v7
裝置支援的API級別。如v1代表API級別1(帶有Android1.0或更高版的裝置),v4代表API級別4(帶有Android1.6或更高版本的裝置)
警告:Android1.5和1.6只有在限定符跟平臺版本完全匹配時,才能匹配資源

相關文章