ComptibilityInfo.java
http://www.tuicool.com/articles/ZZZRNf
andorid界面單位開發是應該是dip
自適應,包括元素大小自適應,和位置自適應。
元素大小:
圖片默認會自適應的。
dip會自適應。
自適應問題。一個公式 px=dip*(density/160);(density/160)在android系統中對應 DisplayMetrics.density在一固定的手機上它是一個常數,0.75,1,1.5。等。有了這個常數用dip做單位在不同手機上就有不同的px了。這就是縮放原理。
drawable-hdpi、drawable-mdpi、drawable-ldpi中的圖片是自動選擇的。但是如果對應的文件夾下沒有所需的圖片它會在其他兩個文件夾下尋找,找到了按density縮放。
元素坐標:
圖片坐標,和觸屏事件坐標。 都用相對坐標 。
自適應原則:圖片縮放自適應,位置用相對位置(單位也用dip)。
所有的機型寬都是相等的dip數,高不一定是相等的dip數。
240x320 density=120 320dipx426.6dip
320x480 density=160 320dipx480dip
480x800 density=240 320dipx533.3dip
480x854 density=240 320dipx569.33dip
我感覺,做手機的屏幕自適應比做web的瀏覽器兼容更麻煩..以下是搜到的資料,原來android還有這些不為人知的東西: 一:不同的layout Android手機屏幕大小不一,有480x320, 640x360, 800x480.怎樣才能讓App自動適應不同的屏幕呢? 其實很簡單,只需要在res目錄下創建不同的layout文件夾,比如layout-640x360,layout-800x480,所有的layout文件在編譯之后都會寫入R.java里,而系統會根據屏幕的大小自己選擇合適的layout進行使用。 二:hdpi、mdpi、ldpi 在之前的版本中,只有一個drawable,而2.1版本中有drawable-mdpi、drawable-ldpi、drawable-hdpi三個,這三個主要是為了支持多分辨率。 drawable- hdpi、drawable- mdpi、drawable-ldpi的區別: (1)drawable-hdpi里面存放高分辨率的圖片,如WVGA (480x800),FWVGA (480x854) (2)drawable-mdpi里面存放中等分辨率的圖片,如HVGA (320x480) (3)drawable-ldpi里面存放低分辨率的圖片,如QVGA (240x320) 系統會根據機器的分辨率來分別到這幾個文件夾里面去找對應的圖片。 在開發程序時為了兼容不同平台不同屏幕,建議各自文件夾根據需求均存放不同版本圖片。
1.術語和概念
| 術語 |
說明 |
備注 |
| Screen size(屏幕尺寸) |
指的是手機實際的物理尺寸,比如常用的2.8英寸,3.2英寸,3.5英寸,3.7英寸 |
摩托羅拉milestone手機是3.7英寸 |
| Aspect Ratio(寬高比率) |
指的是實際的物理尺寸寬高比率,分為long和nolong |
Milestone是16:9,屬於long |
| Resolution(分辨率) |
和電腦的分辨率概念一樣,指手機屏幕縱、橫方向像素個數 |
Milestone是854*480 |
| DPI(dot per inch) |
每英寸像素數,如120dpi,160dpi等,假設QVGA(320*240)分辨率的屏幕物理尺寸是(2英寸*1.5英寸),dpi=160 |
可以反映屏幕的清晰度,用於縮放UI的 |
| Density(密度) |
屏幕里像素值濃度,resolution/Screen size可以反映出手機密度, |
|
| Density-independent pixel (dip) |
指的是邏輯密度計算單位,dip和具體像素值的對應公式是dip/pixel=dpi值/160,也就是 px = dp * (dpi / 160) |
|
2. DPI值計算
比如:計算WVGA(800*480)分辨率,3.7英寸的密度DPI,如圖1所示
圖1
Diagonal pixel表示對角線的像素值(=
),DPI=933/3.7=252
3.手機屏幕的分類
3.1根據手機屏幕密度(DPI)或屏幕尺寸大小分為以下3類,如圖2所示
圖2
3. 2手機屏幕分類和像素密度的對應關系如表1所示:
|
|
Low density (120), ldpi |
Medium density (160), mdpi |
High density (240), hdpi |
| Small screen |
QVGA (240x320) |
|
|
| Normal screen |
WQVGA400 (240x400)WQVGA432 (240x432) |
HVGA (320x480) |
WVGA800 (480x800)WVGA854 (480x854) |
| Large screen |
|
WVGA800* (480x800)WVGA854* (480x854) |
|
表1
3.3手機尺寸分布情況( http://developer.android.com/resources/dashboard/screens.html )如圖3所示,目前主要是以分辨率為800*480和854*480的手機用戶居多

圖3
從以上的屏幕尺寸分布情況上看,其實手機只要考慮3-4.5寸之間密度為1和1.5的手機
4 UI設計
從開發角度講,應用程序會根據3類Android手機屏幕提供3套UI布局文件,但是相應界面圖標也需要提供3套,如表2所示
| Icon Type |
Standard Asset Sizes (in Pixels), for Generalized Screen Densities |
||
|
|
Low density screen (ldpi) |
Medium density screen (mdpi) |
High density screen (hdpi) |
| Launcher |
36 x 36 px |
48 x 48 px |
72 x 72 px |
| Menu |
36 x 36 px |
48 x 48 px |
72 x 72 px |
| Status Bar |
24 x 24 px |
32 x 32 px |
48 x 48 px |
| Tab |
24 x 24 px |
32 x 32 px |
48 x 48 px |
| Dialog |
24 x 24 px |
32 x 32 px |
48 x 48 px |
| List View |
24 x 24 px |
32 x 32 px |
48 x 48 px |
表2
5 如何做到自適應屏幕大小呢?
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有個自動匹配機制去選擇對應的布局和圖片資源
今天一個開發者問到我為什么游戲開發要刪除項目下的hdpi、mdpi和ldpi文件夾;下面詳細給大家解答一下:
首先童鞋們如果看過我寫的《 【Android游戲開發二十一】Android os設備謊言分辨率的解決方案! 》這一節的話都應該知道Android從1.6和更高,Google為了方便開發者對於各種分辨率機型的移植而增加了自動適配的功能;
自動適配的原理很簡單,只要你建立的項目是1.6或者更高都會看到項目下有drawable-hdpi、drawable-mdpi、drawable-ldpi 三個文件夾,這三個文件夾分別放置高清分辨率、中分辨率、低分辨率的資源文件;那么如果你的項目在高清分辨率上運行的話,系統會默認索引drawable-hdpi文件夾下的資源,其他雷同;
那么既然系統會自動找匹配的文件夾,那么肯定會出現找不到的情況,比如當前你的應用在高清分辨率運行,假設代碼中加載一張“himi.png”的圖,那么系統首先會去drawable-hdpi文件夾下去找這張圖,一旦找不到,系統會再到其他drawable下尋找,再假設你其實把這張“himi.png”放在了drawable-mdpi中,那么系統會默認把這張圖片放大;反之一樣,如果你在低分辨率中運行加載一張圖片的話,一旦你將圖片放入高清的drawable-dpi中,那么系統默認縮小這張圖;
總結來說:如果你的應用想適配高、中、低分辨率,那么你需要有3套圖放入對應的文件夾中,這樣系統會智能加載;如果你就想保留一個文件夾,不想讓系統智能尋找縮放的話,有兩種方式可以解決:
1.刪除drawable-hdpi、drawable-mdpi、drawable-ldpi三個文件夾,創建一個drawable文件夾即可;
2.將資源文件放入assets中,因為assets中的資源系統永遠不會為其生成id,所以不會智能縮放;
-------------------下面介紹第二點,如何讓你的游戲應用高清
其實還是在《 【Android游戲開發二十一】Android os設備謊言分辨率的解決方案! 》中介紹過,1.6后android有了智能判斷的緣故,你獲取的屏幕寬高其實是不准確的,詳情可以參考 【Android游戲開發二十一】Android os設備謊言分辨率的解決方案! 》;那么這里要補充一點就是:
如果你在AndroidMainFest 中,定義 <uses-sdk android:minSdkVersion="4" /> 就OK了!你會發現你的圖片很清楚,其實也是因為android自動縮放造成的,上面說了,一般獲取的分辨率會不正常(比正確的偏小)那么一旦你加上這一句之后,你的分辨率就正常了,所以就明顯游戲質量高了一個檔次。
這里再補充一下: 一旦你定義了<uses-sdk android:minSdkVersion="4" />,就是限制1.5SDK的手機無法安裝你的程序;
OK,繼續忙了,大家嘗試下吧~
1.Screen size 屏幕實際尺寸。 Android講屏幕實際尺寸分為3個通用的尺寸。 2.Aspect ratio 長寬比
3.Resolution 分辨率
4.Density 密度
5.Density-independent pixel 密度無關的像素
介紹:Adnroid1.6或以上SDK,在AndroidManifest.xml中提供新的一個元素<supports-screens>用於支持多屏幕機制。 <supports-screens android:largeScreens="true" 是否支持大屏 android:normalScreens="true" 是否支持中屏 android:smallScreens="true" 是否支持小屏 android:anyDensity="true" 是否支持多種不同密度 />
Android提供3種方式處理屏幕自適應 一.預縮放的資源(基於尺寸和密度去尋找圖片) 1.如果找到相應的尺寸和密度,則利用這些圖片進行無縮放小時。 2.如果沒法找到相應的尺寸,而找到密度,則認為該圖片尺寸為 "medium",利用縮放這個圖片顯示。 3.如果都無法匹配,則使用默認圖片進行縮放顯示。默認圖片默認標配 "medium" (160)。
二.自動縮放的像素尺寸和坐標(密度兼容) 1.如果應用程序不支持不同密度android:anyDensity="false",系統自動縮放圖片尺寸和這個圖片的坐標。 (代碼中體現) 2.對於預縮放的資源,當android:anyDensity="false",也不生效。 3.android:anyDensity="false",只對密度兼容起作用,尺寸兼容沒效果
三.兼容模式顯示在大屏幕,尺寸(尺寸兼容) 1.對於你在<supports-screens>聲明不支持的大屏幕,而這個屏幕尺寸是normal的話,系統使用尺寸為 ("normal")和密度為("medium)顯示。 2. 對於你在<supports-screens>聲明不支持的大屏幕,而這個屏幕尺寸是larger的話,系統同樣使用尺寸為 ("normal")和密度為("medium)顯示,不過會出現一層黑色的背景。不是居中顯示。
密度獨立: 系統默認應用支持DIP單位的,三個使用DIP的地方: 1.加載資源時,使用DIP實現預縮放的資源。 2.在Layout使用DIP,系統自動完成縮放。 3.在應用程序中,自動縮放一些絕對像素。 (只有在android:anyDensity="false"生效)即屏幕自適應方式二 4.像素單位都使用DIP,文本單位使用SP
最佳屏幕獨立實踐: 1.使用wrap_content, fill_parent 和使用dip作為像素單位in XML layout files。 2.避免使用AbsoluteLayout 3.在代碼中,不要使用像素數字硬編碼,而是要通過dip轉換為px。 例子: 你使用手勢分析器分析一個scroll手勢,假如,你滾動的距離是16px。 1.在一個160dip的屏幕中,你實際移動距離 16px / 160dpi = 1/10th of an inch (or 2.5 mm) 2.在一個240dip的屏幕中,你實際移動距離 16px / 240dpi = 1/15th of an inch (or 1.7 mm) // The gesture threshold expressed in dip private static final float GESTURE_THRESHOLD_DIP = 16.0f; // Convert the dips to pixels final float scale = getContext().getResources().getDisplayMetrics().density; mGestureThreshold = (int) (GESTURE_THRESHOLD_DIP * scale); 4.使用密度和/或尺寸特定資源(通過文件夾)
關於預縮放或者自動縮放圖片或9格圖 1.系統是一定對會資源包下的圖片進行合理的縮放。 例如:一張240x240高密度圖片,顯示在中密度的屏幕上,圖片大小自動變為160x160。 2.你在API中不會得到被縮放后的圖片尺寸,得到還是你原來圖片的尺寸。 3.如果你不想系統自動幫你縮放圖片,可以建立一個res/drawable-nodpi文件夾,存放你的圖片。 4.也可以通過BitmapFactory.Options 完成系統自動縮放圖片或9格圖(在畫圖時)。 5.自動縮放圖片比預縮放花費更多CPU,但是用更少內存(RAM or ROM ?)
一、相關概念
a) android支持density的版本 Android從1.6版本開始支持density(對應API Level 4)
b) density density值表示每英寸有多少個顯示點,比如240就是每英寸240個點,它是針對設備的屬性,它是屏幕物理長寬的擴展,給屏幕設置為低密度顯示的內容少,同樣的條件下,密度小的屏幕顯示同樣的按鈕看起來大,高密度的看起來小
c) 分辨率 是整個屏是多少點,比如800x480,它是對於軟件來說的顯示單位,以px為單位的點
d) 設置density的效果 不同density下屏幕分辨率信息,以480dip*800dip的WVGA為例 density=120時 屏幕實際分辨率為240px*400px density=160時 屏幕實際分辨率為320px*533px density=240時 屏幕實際分辨率為480px*800px
二、相關代碼及設置
a) AndroidManifest.xml <supports-screens android:anyDensity="true"/> <uses-sdk android:minSdkVersion="4"></uses-sdk>
b) 資源目錄名(android 2.0以后) res/xxx-hdpi 當density為240時,使用此目錄下的資源 res/xxx-mdpi 當density為160時,使用此目錄下的資源 res/xxx-ldpi 當density為120時,使用此目錄下的資源 res/xxx 不常后綴,為默認設置,同xxx-mdpi 如果硬件相應的desity的目錄不存在,系統會利用存在的density自動乘以系數計算出相應的density
c) 資源單位(layout xml文件中定義大小的單位)
i. dp=dip=dx ( Density independent pixel ) 基於屏幕密度的抽象單位,布局時盡量使用單位dip,少使用px dip是 應用用於定義UI的虛擬單位,用於說明與密度無關的尺寸和位置。 dip點等價於160dpi密度中的一個物理點,密度由平台決定,換算公式如下 pixels = dips * (density / 160) , 160DPI的密度系數是1 例如 240 dpi的屏幕,1個dip點等於1.5個物理點
ii. px 設置的絕對點數, 如果使用更高density的系統, 控件就會變小
三、設置density 設置系統變量hw.lcd.density,可設置density
四、實現density的關鍵源碼
a) BitmapFactory.java
b) ComptibilityInfo.java
