轉(zhuǎn)載地址:https://mp.weixin.qq.com/s/e26d6s3hpWJOmhA4AUqRbQ?utm_source=androidweekly.cn&utm_medium=website
為什么要適配
由于Android系統(tǒng)的開放性,任何用戶、開發(fā)者、硬件廠商、運(yùn)營(yíng)商都可以對(duì)Android系統(tǒng)和硬件進(jìn)行定制,修改成他們想要的樣子。
但是這種“碎片化”到達(dá)什么程度呢?
以上每一個(gè)矩形都代表一種機(jī)型,且它們屏幕尺寸、屏幕分辨率大相徑庭。隨著Android設(shè)備的增多,設(shè)備碎片化、品牌碎片化、系統(tǒng)碎片化、屏幕碎片化的程度也在不斷加深。
為了讓我們的Android應(yīng)用在各式各樣的手機(jī)上運(yùn)行的時(shí)候,能夠保持界面效果一直,所以,我們需要對(duì)各種手機(jī)屏幕進(jìn)行適配!
概念
1、像素(px)
通常所說(shuō)的像素,就是CCD/CMOS上光電感應(yīng)元件的數(shù)量,一個(gè)感光元件經(jīng)過(guò)感光,光電信號(hào)轉(zhuǎn)換,A/D轉(zhuǎn)換等步驟以后,在輸出的照片上就形成一個(gè)點(diǎn),我們?nèi)绻延跋穹糯髷?shù)倍,會(huì)發(fā)現(xiàn)這些連續(xù)色調(diào)其實(shí)是由許多色彩相近的小方點(diǎn)所組成,這些小方點(diǎn)就是構(gòu)成影像的最小單位“像素”(Pixel)。
簡(jiǎn)而言之,像素就是手機(jī)屏幕的最小構(gòu)成單元。
2、分辨率
手機(jī)在橫向、縱向上的像素點(diǎn)數(shù)總和,一般描述成 寬*高 ,
即橫向像素點(diǎn)個(gè)數(shù)縱向像素點(diǎn)個(gè)數(shù)*。
3、屏幕尺寸(in)
手機(jī)對(duì)角線的物理尺寸,單位 英寸(inch),一英寸大約2.54cm,常見(jiàn)的尺寸有4.7寸、5寸、5.5寸、6寸
4、屏幕像素密度(dpi)
每英寸長(zhǎng)度上像素點(diǎn)個(gè)數(shù)。
例如每英寸內(nèi)有160個(gè)像素點(diǎn),則其像素密度為160dpi。
公式: 像素密度=像素/尺寸 (dpi=px/in)
5、標(biāo)準(zhǔn)屏幕像素密度(mdpi)
每英寸長(zhǎng)度上還有160個(gè)像素點(diǎn),即稱為標(biāo)準(zhǔn)屏幕像素密度(mdpi)。
6、像素密度等級(jí)
手機(jī)真實(shí)像素密度與標(biāo)準(zhǔn)屏幕像素密度(160dpi)的比值。官方給出的0.75、1、1.5、2、3、4,即對(duì)應(yīng)120dpi、160dpi、240dpi、320dpi、480dpi、640dpi。
7、密度無(wú)關(guān)像素(dp)
density-independent pixel,叫dp或dip,與終端上的實(shí)際物理像素點(diǎn)無(wú)關(guān)??梢员WC在不同屏幕像素密度的設(shè)備上顯示相同的效果,是安卓特有的長(zhǎng)度單位。
8、獨(dú)立比例像素(sp)
scale-independent pixel,叫sp或sip,字體大小專用單位,可根據(jù)字體大小首選項(xiàng)進(jìn)行縮放;
推薦使用12sp、14sp、18sp、22sp作為字體大小,不推薦使用奇數(shù)和小數(shù),容易造成精度丟失,12sp以下字體太小。
9、尺寸、像素、像素密度關(guān)系
10、px與dp關(guān)系
像素=dp像素密度等級(jí),即px=dp(dpi/160)**
對(duì)哪些設(shè)備適配
注意進(jìn)行Android設(shè)備的屏幕適配操作,不是單單對(duì)屏幕尺寸多樣的各種設(shè)備進(jìn)行的適配,在諸多的物理尺寸的背后是屏幕的分辨率,現(xiàn)在市面上占比最多的六種分辨率:480800、320480、480854、540960、7201280、10801920。在日常適配中只要做好對(duì)這幾個(gè)設(shè)備的適配,就能很好的適配其他機(jī)型。但是在這幾種分辨率的背后存在的更為根本的數(shù)據(jù)是設(shè)備的屏幕像素密度。在Google文檔中對(duì)于屏幕的像素密度進(jìn)行了幾種規(guī)定!
另外也需注意對(duì)安卓平板、安卓電視等大尺寸、超大尺寸設(shè)備的適配。
如何適配
1、適配誤區(qū)
在進(jìn)行適配的時(shí)候,人們總是關(guān)注于:代碼、Layout、Dimens、圖片、權(quán)重,這幾種適配方式并不是屏幕適配的全部方案,除此之外還存在多種小細(xì)節(jié)來(lái)實(shí)現(xiàn)屏幕適配。
如何理解使用dp為單位進(jìn)行適配?:

但是,使用密度無(wú)關(guān)像素(dp)也不能做到適配所有屏幕!
2、造成誤差原因
在長(zhǎng)期的Android發(fā)展過(guò)程中,由于Android設(shè)備的增多,Google制定的屏幕密度標(biāo)準(zhǔn)(mdpi、hdpi、ldpi等),在眾多廠家的生產(chǎn)過(guò)程中,已經(jīng)被打破,人們沒(méi)有生產(chǎn)數(shù)完全符合屏幕密度標(biāo)準(zhǔn)的Android設(shè)備,對(duì)于真實(shí)手機(jī)的屏幕密度值,是在Google標(biāo)準(zhǔn)的周圍浮動(dòng)變化的,但是不乏存在一些廠商生產(chǎn)的設(shè)備偏離Google的屏幕密度標(biāo)準(zhǔn)比較大,這個(gè)時(shí)候再使用dp作為單位就不能完完全全的完成適配操作?。╠p只有在大家標(biāo)準(zhǔn)統(tǒng)一的情況下才有更好的發(fā)展)
在所有計(jì)算公式中存在誤差:在計(jì)算真實(shí)像素密度時(shí)運(yùn)用了開方運(yùn)算和除法運(yùn)算,導(dǎo)致所得結(jié)果存在誤差。
理論計(jì)算造成的誤差:
在計(jì)算對(duì)角線上像素點(diǎn)個(gè)數(shù)時(shí),我們使用勾股定理計(jì)算得出,但實(shí)則存在誤差:
若將像素長(zhǎng)度當(dāng)做1,分辨率指的是橫縱向上的1的個(gè)數(shù),計(jì)算記過(guò)表示的是對(duì)角線上有多少個(gè)1,但理論上對(duì)角線上 根號(hào)2 的個(gè)數(shù)才是像素點(diǎn)的個(gè)數(shù)!
屏幕對(duì)角線并不會(huì)和像素對(duì)角線重合,使計(jì)算結(jié)果存在誤差。

3、ldpi、mdpi、hdpi、xhdpi、xxhdpi的使用
官方截圖:


4、使用wrap_content、match_parent、權(quán)重
要確保布局的靈活性并適應(yīng)各種尺寸的屏幕,應(yīng)使用 “wrap_content” 、“match_parent”和權(quán)重控制某些視圖組件的寬度和高度。
使用 “wrap_content”,系統(tǒng)就會(huì)將視圖的寬度或高度設(shè)置成所需的最小尺寸以適應(yīng)視圖中的內(nèi)容,而 “match_parent”(在低于 API 級(jí)別 8 的級(jí)別中稱為 “fill_parent”)則會(huì)展開組件以匹配其父視圖的尺寸。
如果使用 “wrap_content” 和 “match_parent” 尺寸值而不是硬編碼的尺寸,視圖就會(huì)相應(yīng)地僅使用自身所需的空間或展開以填滿可用空間。此方法可讓布局正確適應(yīng)各種屏幕尺寸和屏幕方向。
5、使用相對(duì)布局,不要使用絕對(duì)布局
我們大部分時(shí)候使用的都是線性布局、相對(duì)布局和幀布局,絕對(duì)布局由于適配性極差,所以極少使用。
關(guān)于布局的使用應(yīng)該具體情況具體分析,在進(jìn)行電視機(jī)頂盒的開發(fā)中就是使用的是絕對(duì)布局。
6、使用限定符進(jìn)行適配操作
使用尺寸限定符——large
使用最小寬度限定符——swdp
使用屏幕方向限定符
7、多套layout適配
res/values/layouts.xml:
res/values-sw600dp-land/layouts.xml:
res/values-sw600dp-port/layouts.xml:
res/values-large-land/layouts.xml:
res/values-large-port/layouts.xml:
8、使用自動(dòng)拉伸位圖
支持各種屏幕尺寸通常意味著您的圖片資源還必須能適應(yīng)各種尺寸。例如,無(wú)論要應(yīng)用到什么形狀的按鈕上,按鈕背景都必須能適應(yīng)。
如果在可以更改尺寸的組件上使用了簡(jiǎn)單的圖片,您很快就會(huì)發(fā)現(xiàn)顯示效果多少有些不太理想,因?yàn)橄到y(tǒng)會(huì)在運(yùn)行時(shí)平均地拉伸或收縮您的圖片。解決方法為使用自動(dòng)拉伸位圖,這是一種格式特殊的 PNG 文件,其中會(huì)指明可以拉伸以及不可以拉伸的區(qū)域。
.9的制作,實(shí)際上就是在原圖片上添加1px的邊界,然后按照我們的需求,把對(duì)應(yīng)的位置設(shè)置成黑色線,系統(tǒng)就會(huì)根據(jù)我們的實(shí)際需求進(jìn)行拉伸。
9、普通圖片處理
稍后會(huì)詳細(xì)介紹。
10、dimens使用

如上圖,我將市面上各分辨率下的屏幕尺寸,取了平均數(shù),算出對(duì)應(yīng)的真實(shí)的屏幕像素密度,與理論要求的屏幕像素密度作了對(duì)比,比值在倒數(shù)第二列。發(fā)現(xiàn):(干貨要來(lái)了?。┱鎸?shí)像素密度與理論像素密度的比值大致分為兩類,取其平均數(shù),一類在1.15左右,另一類則在0.89左右。巧了,它們兩類正好各自對(duì)應(yīng)w320dp和w360dp的寬度限定符!所以,dimens只需寫兩套即可(values-w320dp、values-w360dp),其name與真實(shí)數(shù)值的比值就是剛剛我們算出的兩個(gè)平均數(shù)! 以后我們就不需要對(duì)應(yīng)各種分辨率寫多套dimens了,兩套dimens即可。
圖片處理
1、logo
logo需要3636、4848、7272、9696、144144、192192px,圖片使用正方形形狀,在某些機(jī)型上面,會(huì)自動(dòng)顯示為圓角正方形;
Android8.0以后,系統(tǒng)增加了logo點(diǎn)擊效果和動(dòng)畫,可按以上尺寸制作圓形logo,但圖片必須為正方形,圓形以外區(qū)域透明。
2、普通圖片
UI切圖只需按照720*1280,4.7寸屏幕切圖即可;
應(yīng)為iphone6等分辨率、尺寸、像素密度都與要求接近,可使用IOS的2x圖代替。
3、純色圖、.9圖
純色按鈕或漸變按鈕可使用代碼設(shè)置顏色或.9圖實(shí)現(xiàn),不必用圖片作為背景。
4、動(dòng)畫、自定義view、shape
可以使用代碼進(jìn)行控制和展示多種視圖,如patch動(dòng)畫替代幀動(dòng)畫。
5、ImageView的ScaleType
關(guān)于ScaleType請(qǐng)參考這里: http://blog.csdn.net/jiashuai94/article/details/77673625
其他
1、代碼適配
在代碼中使用Google提供的API對(duì)設(shè)備的屏幕寬度進(jìn)行測(cè)量,然后按照需求進(jìn)行設(shè)置。
幾個(gè)主要使用的API:
對(duì)于當(dāng)前控件的寬高設(shè)置,需要做的操作是首先要獲取到該控件的父控件,使用父控件對(duì)當(dāng)前控件的寬高進(jìn)行設(shè)置操作!
API
DisplayMetrics metrics = new DisplayMetrics ();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
手機(jī)對(duì)應(yīng)的寬高:
Constants.screenHeight= metrics.heightDixels;
Constants.screenWidth= metrics.widthDixels;
RelativeLayout.LayoutParams=new RelativeLayout.LayoutParams();
(int)( Constants.screenHeight*0.5+0.5f);
(int)( Constants.screenWidth *0.5+0.5f);
在上面的兩個(gè)計(jì)算操作中最后加上0.5f的作用是:進(jìn)行float強(qiáng)轉(zhuǎn)到int類型的時(shí)候會(huì)出現(xiàn)都是精度的問(wèn)題。當(dāng)使用Java代碼進(jìn)行寬高設(shè)置的時(shí)候,假如出現(xiàn)320.2dp這樣的數(shù)據(jù)此時(shí)直接進(jìn)行int得到的值是320;但是假如出現(xiàn)320.7這樣的數(shù)據(jù)的時(shí)候,由于int的計(jì)算規(guī)則,會(huì)直接強(qiáng)轉(zhuǎn)為320,但是從實(shí)際出發(fā),這個(gè)時(shí)候的值取321更為合適。
所以在計(jì)算的最后直接加0.5,這樣一來(lái),320.2+0.5=320.7,進(jìn)行數(shù)據(jù)的強(qiáng)轉(zhuǎn)操作得到的數(shù)據(jù)是320,320.7+0.5=321.2,進(jìn)行數(shù)據(jù)強(qiáng)轉(zhuǎn)操作得到的數(shù)據(jù)是321,這樣一來(lái)得到的數(shù)據(jù)就和實(shí)際預(yù)想的更為接近??!
2、接口配合
本地加載圖片前判斷手機(jī)分辨率或像素密度,向服務(wù)器請(qǐng)求對(duì)應(yīng)級(jí)別圖片。