1. 引論html
衆所周知,Android機型尺寸各類各樣,因而屏幕適配就成了Android開發中很重要的一環。Android屏幕適配可能一些開發者都會遇到這樣的問題,、java
今天就來分享下屏幕適配,其實Android屏幕適配也能夠很簡單。android
參考:1. http://www.cnblogs.com/yaozhongxiao/archive/2014/07/14/3842908.html網絡
2. http://www.cnblogs.com/ycxyyzw/p/3889939.htmlide
2. Android下尺寸的基本單位函數
① px 像素工具
是英文單詞pixel的縮寫,意爲像素,屏幕上的點。咱們一般所說的分辨率如480X800就是指的像素。佈局
px是個絕對單位,在不一樣尺寸的手機設備下,像素固定顯示效果就是同樣的!字體
在設計領域中,像素是用來計算數碼影像的最小單位。計算機中顯示的圖像並不是連續的線條組成,而是由許多肉眼看不見的小點組成。google
若是把影像放大數倍,會發現這些連續色調實際上是由許多色彩相近的小點所組成,這些小點就是構成影像的最小單位「像素」。因爲是最小的獨立顯示單位,px均爲整數,不會出現0.5px的狀況。
② in 英寸
表示英寸,是屏幕的物理尺寸。每英寸等於2.54釐米。例如咱們常常說的手機屏幕大小有,5(英)寸、4(英)寸就是指這個單位。這些尺寸是屏幕的對角線長度。若是手機的屏幕是4英寸,表示手機的屏幕
(可視區域)對角線長度是4 X 2.54 = 10.16釐米。
應該明白咱們常說的屏幕是4寸指的是:屏幕對角線是4寸
③ dpi 每英寸包含像素個數
dpi是Dots Per Inch的縮寫, 每英寸點數,即每英寸包含像素個數。好比320X480分辨率的手機,寬2英寸,高3英寸, 每英寸包含的像素點的數量爲320/2=160dpi(橫向)或480/3=160dpi(縱向),160
就是這部手機的dpi,橫向和縱向的這個值都是相同的,緣由是大部分手機屏幕使用正方形的像素點。常見取值 120,160,240。通常稱做像素密度,簡稱密度
④ density 屏幕密度
屏幕密度,density和dpi的關係爲 density = dpi/160,爲了與dpi稱呼區別通常叫作屏幕密度,或者直接教density
⑤ dp 設備獨立像素
也即dip,設備獨立像素,device independent pixels的縮寫,Android特有的單位,常見取值 1.5 , 1.0 。和標準dpi的比例(160px/inc)即在屏幕密度dpi = 160屏幕上,1dp = 1px。
⑥ sp 放大像素
與sp相似(設備獨立),主要用於字體顯示,和dp的區別是它能夠根據用戶的字體大小偏好來縮放。
注意點1: pixs = dips * (dpi/160) 也就是說相同的dip(dp)在不一樣的屏幕密度下會表明不一樣個像素點
如: 定義一個矩形10 x 10dip.在分辨率爲160dpi的屏上,好比G1,正好是10 x 10像素。而在240 dpi的屏,則是15 x 15像素
注意點2:根據google的推薦,統一使用dip,字體則使用sp,這樣更好看
3. 各單位的轉換
① 計算dpi與屏幕密度density
dpi = (px/inch) /(160 px/inch)
好比一個機器,屏幕4寸,分辨率480X800,他的dpi能算麼。
由於不知道邊長,確定不能分開算,4 寸是對角線長度,那直接用勾股定理算對角線像素,除以4,算出來大概是 dpi = 233 像素/英寸。
那麼density就是 (233 px/inch)/(160 px/inch)=1.46 左右
順帶說下,android默認的只有3個dpi,low、medium和high,對應 120、160、240,若是沒有特別設置,全部的dpi都會被算成這3個,其中的default就是160。
② dp與px 設備獨立像素與像素的轉換
咱們寫佈局的時候,確定仍是要知道1個dp到底有多少px的。
換算公式以下: dp = (DPI/(160像素/英寸))px = density px ,也就是 屏幕密度×像素 = 獨立設備像素
假設dpi是240 像素/英寸 , 那麼density就是1.5,那麼就是 1dp=1.5px
③ 爲何咱們在佈局時儘可能要用dip,而不是px?
http://www.cnblogs.com/yaozhongxiao/archive/2014/07/14/3842908.html
4. android Drawble目錄
drawable-ldpi (dpi=120, density=0.75)
drawable-mdpi (dpi=160, density=1)
drawable-hdpi (dpi=240, density=1.5)
drawable-xhdpi (dpi=320, density=2)
drawable-xxhdpi (dpi=480, density=3)
能夠看到drawable文件夾,分別對應不一樣的dpi
古老方案:市面上的一些Android教程大多都是教的是爲每種dpi都出一套圖片資源,這個當然是一種解決辦法,但同時也是一種很是笨的方法,爲美工或者設計增長了很多的工做量不說,同時也會讓你的apk包
變的很大。那麼有沒有什麼好的方法既能保證屏幕適配,又能夠最小佔用設計資源,同時最好又只使用一套dpi的圖片資源呢?
首先必須清楚一個自動渲染的概念,Android SDK會自動屏幕尺寸選擇對應的資源文件進行渲染,如SDK檢測到你手機dpi是160的話會優先到drawable-mdpi文件夾下找對應的圖片資源,注意只是優先,假設
你手機dpi是160,可是你只在xhpdi文件夾下有對應的圖片資源文件,程序同樣能夠正常運行。因此理論上來講只須要提供一種規格的圖片資源就ok了,若是隻提供ldpi規格的圖片,對於大分辨率的手機若是把
圖片放大就會不清晰,因此須要提供一套你須要支持的最大dpi的圖片,這樣即便用戶的手機分辨率很小,這樣圖片縮小依然很清晰。
② 重點須要明白:
<View android:layout_height="1dip" android:layout_width="100dip"/>
該View在密度爲160dip的屏幕上顯示的長度爲100px(像素)長,而在320dip的屏幕上它的長度將爲200px。
在圖片處於drawable文件夾內時,也須要作這種轉換。
假如在drawable-mdpi的文件夾內有一張22*44的圖片,經過程序將其讀入系統中時,假設屏幕密度爲320dip,那它在內存中的大小將是44*88。
總結: 本機系統的DPI > 圖片所在文件夾的DPI 圖片將會被放大
本機系統的DPI < 圖片所在文件夾的DPI 圖片將會被縮小
目前主流作法是將圖片放置在drawable-hdpi文件夾內,該文件夾對應的density是240dip,但其實如今的手機通常都是320dip甚至480dip了,
因此放置在hdpi文件夾內的圖片在顯示時都是已經自動拉伸過了。
③ 當圖片是從其餘地方而來,如直接讀取sd卡或assert文件夾內的圖片或網絡下載來時的狀況
首先獲取的不是drawbale對象而是個bitmap對象,該bitmap對象的width和height對應的是圖片的真實像素大小。
而將bitmap對象轉換爲drawable時,除非咱們手動設置了目標density,不然不進行縮放。
BitmapDrawable bmpDrawable = new BitmapDrawable(bitmap);
使用這個構造函數,默認的density是160,該構造函數已經被摒棄了,推薦使用下一個
BitmapDrawable bmpDrawable = new BitmapDrawable(getResources(),bitmap);
該構造函數會經過getResources獲取到手機的density,將其設置爲默認的density。
getResources().getDisplayMetrics().densityDpi
若咱們須要進行縮放,能夠經過下述方法設置目標density。
bmpDrawable.setTargetDensity(160)
在320dip長度的屏幕上,該bmpDrawable將會縮小爲一半。
5. android下尺寸描述工具類
① 獲得屏幕寬和高
public
static
int
getWidth(Context context){
WindowManager wm=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics =
new
DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return
outMetrics.widthPixels;
}
DisplayMetrics的toString()方法以下:
@Override public String toString() { return "DisplayMetrics{density=" + density + ", width=" + widthPixels + ", height=" + heightPixels + ", scaledDensity=" + scaledDensity + ", xdpi=" + xdpi + ", ydpi=" + ydpi + "}"; }
② dp與dx的轉化
** * 根據手機的分辨率從 dip 的單位 轉成爲 px(像素) */ public static int dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } /** * 根據手機的分辨率從 px(像素) 的單位 轉成爲 dp==dip */ public static int px2dip(Context context, float pxValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (pxValue / scale + 0.5f); }