在drawable中的圖片在不同密度的設備上顯示時,在屏幕上的占比是不一樣的。
如:160px的圖片,在800x480的屏幕上顯示:
密度是:
160dpi時,占屏幕的三分之一 (=160px/480px)。
240dpi時,占屏幕的二分之一(>160px/480px)。
如何保持圖片在不同密度的設備上,圖片顯示相同的像素數?
方法A:
為不同密度的設備,准備相應的圖片,放在對應的drawable-?dpi中。
優點:可以為不同密度的設備,准備對應密度的圖片,可以做到圖片在哪種密度上都很清晰細膩。
缺點:圖片比較多,增加圖片制作的工作量;
方法B:
只准備一組圖片,將圖片放到drawable-nodpi中。
優點:減少了圖片的數量;
確定:圖片可能被拉伸而導致不細膩;
方法C:
使用px指定圖片的大小
理解DPI。DPI是密度density的測量單位,dots per inch 每英寸內的像素數。
理解DIP。DIP是指定大小的單位,device independent pixels設備獨立像素。
應該是Density-independent pixel 即與設備的密度無關,有DIP指定的控件大小,在不同密度的設備上,顯示的大小相仿。
pixels = dip * (density / 160)
注:顯示圖片的大小與圖片本身的dpi 沒有關系。
分辨率問題在手機應用上是一個非常重要的問題,舉個簡單例子,默認情況下,一個24×6的圖片,在你做圖的時候,是4個6×6的分割圖片組合成的一個整體圖片,那么在不同density下,如果你切割圖片,這個整體圖片則會出現不同的大小。
1、在160的density(240×320就是160的)模式下,該圖片沒有任何縮放,就是24×6;你用寬6、高6可以正確切片;
2、在240的density(480×800)模式下,該圖片就會被放大1.5倍(240/160),因此,這個圖片實際就是32×9,如果你還用寬6、高6去切片,就會出現問題,這個時候,正確的做法是
要么使用Bitmap的option設置,在從Resource讀取資源的時候,表明不縮放,但默認情況下,Android系統使用dip來讀取你分辨率無關的單位,所以,你必須顯示的設置option,告訴android系統不要使用dip來自適應。
1: private Bitmap decodeResource(Resources resources, int id) {
2: TypedValue value = new TypedValue();
3: resources.openRawResource(id, value);
4: BitmapFactory.Options opts = new BitmapFactory.Options();
5: opts.inTargetDensity = value.density;
6: return BitmapFactory.decodeResource(resources, id, opts);
7: }
但是,這種方法不推薦使用,這樣破環了DIP的初衷,最好以下面兩種方式來處理。
將切片的寬乘1.5,高乘1.5,也就是說,以9×9的寬高去切片。
直接以4分之一去切割。
下面說說官方文檔對分辨率問題的解釋:
http://developer.android.com/guide/practices/screens_support.html
一、多分辨率支持
在設計之初,Android系統就被設計為一個可以在多種不同分辨率的設備上運行的操作系統。對於應用程序來說,系統平台向它們提供的是一個穩定的,跨平台的運行環境,而關於如何將程序以正確的方式顯示到它所運行的平台上所需要的大部分技術細節,都由系統本身進行了處理,無需程序的干預。當然,系統本身也為程序提供了一系列API,所以在目標平台的分辨率是可以完全確定的情況下,程序也可以精確的控制自身在目標平台上的界面顯示方式。
二、術語和概念
屏幕尺寸
屏幕的物理尺寸,以屏幕的對角線長度作為依據(比如2.8寸,3.5寸)。
簡而言之,Android把所有的屏幕尺寸簡化為三大類:大,正常,和小。
程序可以針對這三種尺寸的屏幕提供三種不同的布局方案,然后系統會負責把你的布局方案以合適的方式渲染到對應的屏幕上,這個過程是不需要程序員用代碼來干預的。
屏幕長寬比
屏幕的物理長度與物理寬度的比例。程序可以為制定長寬比的屏幕提供制定的素材,只需要用系統提供的資源分類符long和notlong。
分辨率
屏幕上擁有的像素的總數。注意,雖然大部分情況下分辨率都被表示為“寬度×長度”,但分辨率並不意味着屏幕長寬比。在Android系統中,程序一般並不直接處理分辨率。
密度
以屏幕分辨率為基礎,沿屏幕長寬方向排列的像素。
密度較低的屏幕,在長和寬方向都只有比較少的像素,而高密度的屏幕通常則會有很多 ——甚至會非常非常多——像素排列在同一區域。屏幕的密度是非常重要的,舉個例子,長寬以像素為單位定義的界面元素(比如一個按鈕),在低密度的屏幕上會顯得很大,但在高密度的屏幕上則會顯得很小。
密度無關的像素(DIP)
指一個抽象意義上的像素,程序用它來定義界面元素。它作為一個與實際密度無關的單位,幫助程序員構建一個布局方案(界面元素的寬度,高度,位置)。
一個與密度無關的像素,在邏輯尺寸上,與一個位於像素密度為160DPI的屏幕上的像素是一致的,這也是Android平台所假定的默認顯示設備。在運行的時候,平台會以目標屏幕的密度作為基准,“透明地”處理所有需要的DIP縮放操作。要把密度無關像素轉換為屏幕像素,可以用這樣一個簡單的公式:pixels = dips * (density / 160)。舉個例子,在DPI為240的屏幕上,1個DIP等於1.5個物理像素。我們強烈推薦你用DIP來定義你程序的界面布局,因為這樣可以保證你的 UI在各種分辨率的屏幕上都可以正常顯示。
·三種主要的尺寸:大,正常,小;
·三種不同的密度:高(hdpi),中(mdpi)和低(ldpi)。
低密度(120),ldpi
中密度(160),mdpi
高密度(240),hdpi
小屏幕
·QVGA(240×320),2.6~3.0寸
普通屏幕
·WQVGA(240×400),3.2~3.5寸
·FWQVGA(240×432),3.5~3.8寸
·HVGA(320×480),3.0~3.5寸
·WVGA(480×800),3.3~4.0寸
·FWVGA(480×854),3.5~4.0寸
大屏幕
·WVGA(480×800),4.8~5.5寸
·FWVGA(480×854),5.0~5.8寸
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