Android螢幕适配-資源檔案夾命名與比對規則
說明:本文檔目的為分析android工程res目錄下的資源檔案夾(drawable,values,layout等)在螢幕适配方面的限定與适配方法。
1、 Res下檔案夾命名方式
1. 可用的命名屬性
在文檔1中的表格“Table 2. Configuration qualifier names. ”中有說明(表格太大,不友善在此張貼),表格中的"Configuration"項集就是Android全體可用命名屬性集,表格此項的排列順序即是各個屬性的優先級别順序。
2. 命名方法與要求
1) 命名不區分大小寫;
2) 命名形式:資源名-屬性1-屬性2-屬性3-屬性4-屬性5.....
資源名就是資源類型名,包括:drawable, values, layout, anim, raw, menu, color, animator, xml;
屬性1-屬性2-屬性3-屬性4-屬性5.....就是上述的屬性集内的屬性,如:-en-port-hdpi;
注意:各屬性的位置順序必須遵守優先級從高到低排列!否則編譯不過
3. 執行個體說明
1) 把全部屬性都用上的例子(各屬性是按優先級先後排列出來的)
values-mcc310-en-sw320dp-w720dp-h720dp-large-long-port-car-night-ldpi-notouch-keysexposed-nokeys-navexposed-nonav-v7
2) 上述例子屬性的中文說明
values-mcc310(sim卡營運商)-en(語言)-sw320dp(螢幕最小寬度)-w720dp(螢幕最佳寬度)-h720dp(螢幕最佳高度)-large(螢幕尺寸)-long(螢幕長短邊模式)-port(目前螢幕橫豎屏顯示模式)-car(dock模式)-night(白天或夜晚)-ldpi(螢幕最佳dpi)-notouch(觸摸屏模類型)-keysexposed(鍵盤類型)-nokey(硬按鍵類型)-navexposed(方向鍵是否可用)-nonav(方向鍵類型)-v7(android版本)
2、 定位最佳檔案夾
1. 定位算法

特殊說明:關于螢幕大小size相關的屬性不在步驟1的過濾清除條件裡(dpi屬性和screen size屬性):
1) 對于dpi屬性系統的選擇方法是"best match"---即如果沒有找到準确的屬性,可以接着尋找最接近的屬性檔案夾。例如:我的g7手機,應該是values-hdpi,但如果沒有values-hdpi,則可以找出最接近的檔案夾(先找values-xhdpi到values-mdpi到values最後到values-ldpi,注意values在values-ldpi之前先找到,系統認為values比values-ldpi更接近我的values-hdpi屬性);
2) 對于screen size屬性系統的選擇方法是"向下best match",即如果沒找到準确的屬性,隻可以接着在比自身屬性小的檔案夾裡找最接近的屬性檔案夾。例如:我的g7手機,應該是values-normal,但如果沒有values-normal,則可以找出最接近的檔案夾(先找values再到values-small,注意,系統認為values比values-small更接近我的values-normal屬性,但之後就不會再找values-large與values-xlarge了,因為是"向下best match",large與xlarge都比normal大)。
2. 執行個體說明
工程有如下檔案夾:
drawable/
drawable-en/
drawable-fr-rCA/
drawable-en-port/
drawable-en-notouch-12key/
drawable-port-ldpi/
drawable-port-notouch-12key/
手機屬性:
Locale = en-GB
Screen orientation = port
Screen pixel density = hdpi
Touchscreen type = notouch
Primary text input method = 12key
1) 清除包含任何與手機配置有沖突的屬性的資源檔案夾(藍色字型表現被清除)
drawable/
drawable-en/
drawable-fr-rCA/
drawable-en-port/
drawable-en-notouch-12key/
drawable-port-ldpi/
drawable-port-notouch-12key/
注意:因為dpi屬性使用"best match"選擇,是以drawable-port-ldpi/
沒被清除。
2) 選擇文檔1中的表格“Table 2. Configuration qualifier names. ”最高優先級的屬性(MCC最高,然後依次向下選擇)。
3) 有包含上述屬性的檔案夾嗎?
如果沒有,跳轉步驟2,選擇下一優先級高的屬性;
如果有,繼續步驟4;
4) 清除不包含此屬性的所有檔案夾
drawable/
drawable-en/
drawable-en-port/
drawable-en-notouch-12key/
drawable-port-ldpi/
drawable-port-notouch-12key/
5) 重複步驟2和3,直到步驟4中隻剩下一個檔案夾則傳回。例子中,螢幕方向是下一個最高優先級的屬性,是以可以清除兩個檔案夾:
drawable-en/
drawable-en-port/
drawable-en-notouch-12key/
最終找到的檔案夾就是drawable-en-port/
由上述過程可看出,比對是看最高優先級别的屬性,而不是一共比對到的屬性數量,例如:values-en-normal-hdpi的手機,values-en比對比vaues-normal-hdpi更合适。
3、 備注
1. 文檔1中的表格“Table 2. Configuration qualifier names. ”列出的屬性集并不是一直不變的,有些新屬性是在進階的android version才加入的,系統在識别到此新屬性時會自動加上支援新屬性的android最低版本屬性,例如:xhdpi是android 2.2(sdk[img]/images/smiles/icon_cool.gif" alt="[/img]新加入的,則values-xhdpi系統會自動認為是values-xhdpi-v8,這樣新屬性一定不會在android舊版本中比對到了;
2. 對于指定分辨率的屬性(例如:values-hdpi-1024x600,values-hdpi-960x540,values-mdpi-1024x600),指定分辨率屬性并沒出現在官網的比對屬性集裡,也沒找到對于分辨率屬性的詳細說明,經測試,這個分辨率屬性比對并不準确,例如Galaxy Nexus(1280x720 ),卻可以比對到values-hdpi-1024x600,是以希望最好不使用分辨率屬性。
在工程的default.properties中如果split.density=false,則分辨率适配的時候檔案夾命名不需要與scale相除
例
螢幕分辨率:800x480
density:1.5(240)
檔案夾:values-hdpi-800x480
4、 參考文檔
1 :Android資源螢幕适配官方文檔:
http://developer.android.com/guide/topics/resources/providing-resources.html
一、一些基本概念
1、長度(真實長度):英寸、inch
2、分辨率:density 每英寸像素數 dpi(密度)
3、像素:px
4、dip的公式:px /dip=dpi/160 是以 dip 類似于英寸、長度(dp=dip,sp類似于dip) dip=160*inch
dip= 160/dpi * px
當dip一定時,dpi 越大,px就越大
5、廣義分辨率=長px*寬px
二、常用規律
1、平時我們說 手機的分辨率是 320*480的,其實的這裡的分辨率是相對分辨率
意思是:水準方向上的像素數是320,垂直方向上像素數是480,
分辨率是160(預設是160,意思是每英寸像素數160)
那麼水準方向:320 /160=2英寸
垂直方向:480/160=3英寸
于是乎 螢幕對角線 是根号下4*9=3.6(這就是常說的3.6英寸螢幕)
2、說一個手機的螢幕參數有三個:長寬像素之積(相對分辨率)、真實分辨率(dpi)、對角線長度
3、模拟器的分辨率都是160,是以像素越大,屏越大
4、l、m、h 三個檔案夾是按 真是分辨率dpi 來對應找檔案的。
5、有三種方案解決螢幕适配
(1)按像素比 y/開發時用的螢幕像素=x/使用者裝置像素
(2)按長度 用dip(假設螢幕尺寸基本不變)
(3)按密度 放在l、m、h檔案夾(假設螢幕尺寸基本不變,dpi越大 px越大)
6、如果手機是hdpi,但hdpi裡沒有東西,l裡有東西,程式就會去l裡找圖檔并且把它按比例放大。
7、最全的辦法:單獨适配
螢幕分辨率:1024x600
density:1(160)
檔案夾:values-mdpi-1024x600
螢幕分辨率:1024x600
density:1.5(240)
檔案夾:values-hdpi-683x400 由1024/1.5 600/1.5得到,需要四舍五入。
螢幕分辨率:800x480
density:1(160)
檔案夾:values-mdpi-800x480
螢幕分辨率:800x480
density:1.5(240)
檔案夾:values-hdpi-533x320 由800/1.5 480/1.5得到,需要四舍五入。
以此類推
一般情況下需要建立出values 、values-mdpi 、 values-hdpi檔案夾,以備在一些沒有規定的尺寸螢幕上找不到資源的情況。
8、我的原則,能用拉伸圖檔的就拉伸、能用相對布局的就用相對布局、能用代碼計算寬度就代碼計算。
讓美工出一份 1080*1920 放到XXH
布局時按照:寬:320dip 高 480 dip
9、主流機型參數:
比例 | 0.75 | 1 | 1.5 | 2 | 3 |
最常見的像素長寬 | 240 | 320 | 480 | 640*960 | 960*1440 |
dpi | ~120 | ~160 | ~240 | ~320 | ~480 |
檔案夾 | L | M | H | XH | XXH |
主流機 | 720*1280(紅米、s3、note2) | 720*1280(米2)1080*1920(米3、note3、s4) | |||
1dp =1px | 1dp =2px | 1dp =2.5px | |||
主流機 | note2、紅米、s3 | 米2、米3、s4、note3 |
| Resources for low-density (ldpi) screens (~120dpi). |
| Resources for medium-density (mdpi) screens (~160dpi). (This is the baseline density.) |
| Resources for high-density (hdpi) screens (~240dpi). |
| Resources for extra high-density (xhdpi) screens (~320dpi). |
----------------------------------------------------------------
紅米:
螢幕分辨率為:720 * 1280
絕對寬度:720pixels
絕對高度:1280pixels
邏輯密度:2.0
X 維 :294.96774像素每英尺
Y 維 :285.193像素每英尺
res/drawable下的檔案會做失真壓縮
res/drawable-nodpi下的檔案不做任何處理
=================================
10、擷取螢幕像素的方法
String str = "";
DisplayMetrics dm = new DisplayMetrics();
dm = this.getApplicationContext().getResources().getDisplayMetrics();
int screenWidth = dm.widthPixels;
int screenHeight = dm.heightPixels;
float density = dm.density;
float xdpi = dm.xdpi;
float ydpi = dm.ydpi;
str += "螢幕分辨率為:" + dm.widthPixels + " * " + dm.heightPixels + "\n";
str += "絕對寬度:" + String.valueOf(screenWidth) + "pixels\n";
str += "絕對高度:" + String.valueOf(screenHeight)
+ "pixels\n";
str += "邏輯密度:" + String.valueOf(density)
+ "\n";
str += "X 維 :" + String.valueOf(xdpi) + "像素每英尺\n";
str += "Y 維 :" + String.valueOf(ydpi) + "像素每英尺\n";
感謝那些寫原創部落格的兄弟,可以讓我們省去不少時間!!