Android的碎片化已經(jīng)被噴了好多年,隨著國(guó)內(nèi)手機(jī)廠商的崛起,碎片化也越來(lái)越嚴(yán)重,根據(jù)OpenSignal的最新調(diào)查,2014年市面上有18796種不同的Android設(shè)備,作為開(kāi)發(fā)者,一個(gè)無(wú)法回避的難題就是需要適配各種各樣奇奇怪怪的機(jī)型。
設(shè)備機(jī)型不同必然也會(huì)導(dǎo)致屏幕大小和分辨率(Resolution)的不同,但是無(wú)論分辨率有多大,屏幕有多大,我們手指觸控范圍的大小不會(huì)發(fā)生變化,所以最優(yōu)的適配方式應(yīng)該是指定大小的控件在所有的設(shè)備上的顯示都一樣。
Android的官方文檔對(duì)此也有明確的說(shuō)明
When adding support for multiple screens, applications do not work directly with resolution; applications should be concerned only with screen size and density, as specified by the generalized size and density groups.
所以,適配應(yīng)該與分辨率無(wú)關(guān),只與屏幕大小和屏幕密度相關(guān),以下是與單位相關(guān)的術(shù)語(yǔ):
(1) Screen size 屏幕的尺寸,即對(duì)角線長(zhǎng)度(單位inch-英寸)
(2) Resolution 分辨率,即屏幕的總像素點(diǎn)數(shù)(width * height)
(3) Screen Density屏幕密度,即每單位英寸包含的像素點(diǎn)數(shù)(dots/inches)
(4)Density-independent pixel (dp或dip) 密度無(wú)關(guān)像素,或者說(shuō)是與屏幕密度無(wú)關(guān)的像素。標(biāo)準(zhǔn)是160dip,即1dp對(duì)應(yīng)1個(gè)pixel,計(jì)算公式如:px = dp * (dpi / 160),屏幕密度越大,1dp對(duì)應(yīng)的像素點(diǎn)越多。
一般表示是手機(jī)的實(shí)際物理尺寸,屏幕尺寸指屏幕的對(duì)角線的長(zhǎng)度,單位是英寸,1英寸=2.54厘米。比如常見(jiàn)的屏幕尺寸有3.5、3.7、4.2、5.0、5.5、6.0等。
屏幕上顯示的像素個(gè)數(shù),單位尺寸內(nèi)像素點(diǎn)越多,顯示的圖像就越清楚。單位是px,1px=1個(gè)像素點(diǎn)。
分辨率720*1280表示手機(jī)水平方向的像素為720,垂直方向?yàn)?280.
市場(chǎng)上主流分辨率有:480*800、 720*1280、 1080*1920(其他的早該淘汰了,忽略不計(jì))。
表示屏幕每英寸(inch)的物理長(zhǎng)度內(nèi)包含的像素點(diǎn)數(shù)(dots),即屏幕像素密度。 單位是dpi( Dots Per Inch)
DPI(Dots Per Inch)是印刷行業(yè)中用來(lái)度量空間點(diǎn)密度用的,這個(gè)值是打印機(jī)每英寸可以噴的墨汁點(diǎn)數(shù)。計(jì)算機(jī)顯示設(shè)備從打印機(jī)中借鑒了DPI的概念,由于計(jì)算機(jī)顯示設(shè)備中的原子單位不是墨汁點(diǎn)而是像素,所以就創(chuàng)造了PPI(Pixels Per Inch),這個(gè)值是屏幕每英寸的像素?cái)?shù)量,即像素密度(Screen density)。由于各種原因,目前PPI(主要是iOS)和DPI(主要在Android中)都會(huì)用在計(jì)算機(jī)顯示設(shè)備的參數(shù)描述中,不過(guò)二者的意思是一樣的,都是代表像素密度。
Android設(shè)備用DPI來(lái)表示屏幕密度(Density),屏幕密度大就表示一個(gè)Inch包含的Dot比較多。160DPI的屏幕就表示一個(gè)Inch包含160個(gè)Dot,320DPI的屏幕表示一個(gè)Inch有320個(gè)Dot,所以說(shuō)Dot的大小是不固定的。高DPI屏幕顯示的元素會(huì)比較精細(xì)(看起來(lái)會(huì)比較?。虳PI屏幕顯示的元素相對(duì)來(lái)說(shuō)就比粗糙(看起來(lái)會(huì)比較大)。
通常我們說(shuō)一個(gè)設(shè)備是多少寸時(shí),指的是屏幕對(duì)角線(Diagonal)長(zhǎng)度是多少inch,所以用對(duì)角線的像素值(px)除以對(duì)角線長(zhǎng)度(inch),就可以計(jì)算出PPI。
PPI 計(jì)算公式
為了簡(jiǎn)化適配工作,Android根據(jù)屏幕大?。↖nch)和屏幕密度(DPI)對(duì)設(shè)備做了如下劃分:
你需要把對(duì)應(yīng)dpi的資源放到對(duì)應(yīng)的目錄就可以了,Android會(huì)根據(jù)dpi自動(dòng)選擇資源,目錄規(guī)則如下:
drawable-mdpi/asset.png
drawable-hdpi/asset.png
drawable-xhdpi/asset.png
...
可以看出Android中mdpi與iOS中的1x multiplier所代表的PPI是一樣的,xhdpi與iOS的2x multiplier所代表的PPI一樣,如圖:
既然有那么多不同分辨率、不同大小的屏幕,使用PX必然會(huì)導(dǎo)致適配困難,為了進(jìn)一步簡(jiǎn)化適配工作,Android為我們提供了一個(gè)虛擬的像素單位 - DP 或者 DIP (Density-Independent pixel),當(dāng)然也可以理解為 Device-Independent Pixel,即與設(shè)備屏幕密度無(wú)關(guān)的像素。為什么說(shuō)是虛擬呢,因?yàn)樗拇笮〔皇且粋€(gè)物理(Phisical)值,而是由操作系統(tǒng)根據(jù)屏幕大小和密度動(dòng)態(tài)渲染出來(lái)的。
PX跟DP之間的換算關(guān)系很簡(jiǎn)單:
px = dp * (dpi / 160)
舉例來(lái)說(shuō),小米Pad的屏幕密度為326dpi,如果需要顯示的圖片大小為20dp,那么就需要提供一個(gè) 20*(326/160)=40px
的圖片才能達(dá)到最佳顯示效果,如果還要適配一個(gè)163dpi的屏幕,那么還需要再提供一個(gè)20*(163/160)=20px
的圖片。
那么一個(gè)20dp的圖片,在不同設(shè)備上的顯示效果如何呢?我們以iPad為例來(lái)說(shuō)明。
iPad 屏幕參數(shù)
iPad2 和 iPad Retina的物理尺寸都是 9.7 inch,不同的是分辨率和PPI,一個(gè)是1024x768 / 132ppi,另一個(gè)是2048x1536 / 264ppi,分別計(jì)算一下20dp對(duì)應(yīng)多少inch
ipad2 = 20 * (132 / 160) * (7.9 / (math.sqrt(1024 * 1024 + 768 * 768))) ipad_retina = 20 * (264 / 160) * (7.9 / (math.sqrt(2048 * 2048 + 1536 * 1536)))
計(jì)算結(jié)果都是0.1018359375,這就是dp的功能,它能保證在所有的設(shè)備上顯示的大小都一樣。
SP 全稱是 Scale-independent Pixels,用于字體大小,其概念與DP是一致的,也是為了保持設(shè)備無(wú)關(guān)。因?yàn)锳ndroid用戶可以根據(jù)喜好來(lái)調(diào)整字體大小,所以要使用sp來(lái)表示字體大小。
res目錄下存放項(xiàng)目中的所有動(dòng)畫、圖片、布局、字符串等資源。通常圖標(biāo)放在mipmap目錄下,圖片放在drawable目錄下,布局放在layout目錄下,字符串放在values目錄下, 下面是詳細(xì)描述。
定義預(yù)先確定的動(dòng)畫資源。
Tween動(dòng)畫保存在res/anim/
目錄下,通過(guò)R.anim
類來(lái)訪問(wèn).
Frame動(dòng)畫保存在res/drawable/
目錄下,通過(guò) R.drawable
類來(lái)訪問(wèn).
備注:動(dòng)畫分為兩種,一種是Tween動(dòng)畫、還有一種是Frame動(dòng)畫。Tween動(dòng)畫,這種實(shí)現(xiàn)方式可以使視圖組件移動(dòng)、放大、縮小以及產(chǎn)生透明度的變化;Frame動(dòng)畫,傳統(tǒng)的動(dòng)畫方法,通過(guò)順序的播放排列好的圖片來(lái)實(shí)現(xiàn),類似電影。
定義隨著View狀態(tài)而改變的顏色資源。
保存在 res/color/
目錄下,通過(guò) R.color
類來(lái)訪問(wèn).
定義應(yīng)用程序使用的圖標(biāo)資源。
保存在res/mipmap目錄下,通過(guò)R.mipmap類來(lái)訪問(wèn).
定義bitmap圖像或通過(guò)XML來(lái)定義的圖像資源.
保存在res/drawable/
目錄下,通過(guò)R.drawable
類來(lái)訪問(wèn).
定義應(yīng)用程序UI的布局。
保存在res/layout/
目錄下,通過(guò)R.layout
類來(lái)訪問(wèn).
定義應(yīng)用程序菜單的內(nèi)容。
保存在res/menu/
目錄下,通過(guò)R.menu
類來(lái)訪問(wèn).
定義串、串?dāng)?shù)組、和數(shù)量字符串(zero, one, two, few, many, other)plurals (并且包含串的格式化以及風(fēng)格).
保存在res/values/
目錄下,通過(guò)R.string
, R.array
, 以及R.plurals
類來(lái)訪問(wèn).
定義UI元素的外表與格式(look and format).
保存在res/values/
目錄下,通過(guò)R.style
類來(lái)訪問(wèn).
定義諸如布爾值、顏色、維度、ID、整數(shù)值、整數(shù)數(shù)組、TypedArray的值.
保存在res/values/
目錄下,但每一種是通過(guò)不同的 R
子類(諸如 R.bool
, R.color, R.dimen
, R.id, R.integer
, R.array等)來(lái)訪問(wèn).
參考資料:
[1] 詳解Android開(kāi)發(fā)中常用的 DPI/DP/SP, http://www.jianshu.com/p/913943d25829
[2] 移動(dòng)開(kāi)發(fā)需要知道的像素知識(shí), http://weizhifeng.net/you-should-know-about-dpi.html
[3] 閑話Android 之 屏幕大小、pixel、分辨率、dpi、dip, http://www.cnblogs.com/zhangxinyan/p/3510604.html
[4] Andriod界面設(shè)計(jì)的分辨率和尺寸適配全攻略, http://www.25xt.com/appdesign/8693.html
[5] Resource Types, http://developer.android.com/intl/zh-cn/guide/topics/resources/available-resources.html
[6] More Resource Types, http://developer.android.com/intl/zh-cn/guide/topics/resources/more-resources.html
[7] Managing Projects Overview, http://developer.android.com/intl/zh-cn/tools/projects/index.html#ApplicationModules
聯(lián)系客服