由于Android系統的開放性,任何用戶、開發者、硬件廠商、運營商都可以對Android系統和硬件進行定制,修改成他們想要的樣子。
但是這種“碎片化”到達什么程度呢?
以上每一個矩形都代表一種機型,且它們屏幕尺寸、屏幕分辨率大相徑庭。隨著Android設備的增多,設備碎片化、品牌碎片化、系統碎片化、屏幕碎片化的程度也在不斷加深。
為了讓我們的Android應用在各式各樣的手機上運行的時候,能夠保持界面效果一直,所以,我們需要對各種手機屏幕進行適配!
概念
1、像素(px)
通常所說的像素,就是CCD/CMOS上光電感應元件的數量,一個感光元件經過感光,光電信號轉換,A/D轉換等步驟以后,在輸出的照片上就形成一個點,我們如果把影像放大數倍,會發現這些連續色調其實是由許多色彩相近的小方點所組成,這些小方點就是構成影像的最小單位“像素”(Pixel)。
簡而言之,像素就是手機屏幕的最小構成單元。
2、分辨率
手機在橫向、縱向上的像素點數總和,一般描述成 寬*高 ,
即橫向像素點個數*縱向像素點個數。
3、屏幕尺寸(in)
手機對角線的物理尺寸,單位 英寸(inch),一英寸大約2.54cm,常見的尺寸有4.7寸、5寸、5.5寸、6寸
4、屏幕像素密度(dpi)
每英寸長度上像素點個數。
例如每英寸內有160個像素點,則其像素密度為160dpi。
公式:?像素密度=像素/尺寸 (dpi=px/in)
5、標準屏幕像素密度(mdpi)
每英寸長度上還有160個像素點,即稱為標準屏幕像素密度(mdpi)。
6、像素密度等級
手機真實像素密度與標準屏幕像素密度(160dpi)的比值。官方給出的0.75、1、1.5、2、3、4,即對應120dpi、160dpi、240dpi、320dpi、480dpi、640dpi。
7、密度無關像素(dp)
density-independent pixel,叫dp或dip,與終端上的實際物理像素點無關??梢员WC在不同屏幕像素密度的設備上顯示相同的效果,是安卓特有的長度單位。
8、獨立比例像素(sp)
scale-independent pixel,叫sp或sip,字體大小專用單位,可根據字體大小首選項進行縮放;
推薦使用12sp、14sp、18sp、22sp作為字體大小,不推薦使用奇數和小數,容易造成精度丟失,12sp以下字體太小。
9、尺寸、像素、像素密度關系
10、px與dp關系
像素=dp*像素密度等級,即px=dp*(dpi/160)
對哪些設備適配
注意進行Android設備的屏幕適配操作,不是單單對屏幕尺寸多樣的各種設備進行的適配,在諸多的物理尺寸的背后是屏幕的分辨率,現在市面上占比最多的六種分辨率:480*800、320*480、480*854、540*960、720*1280、1080*1920。在日常適配中只要做好對這幾個設備的適配,就能很好的適配其他機型。但是在這幾種分辨率的背后存在的更為根本的數據是設備的屏幕像素密度。在Google文檔中對于屏幕的像素密度進行了幾種規定!
另外也需注意對安卓平板、安卓電視等大尺寸、超大尺寸設備的適配。
如何適配
1、適配誤區
在進行適配的時候,人們總是關注于:代碼、Layout、Dimens、圖片、權重,這幾種適配方式并不是屏幕適配的全部方案,除此之外還存在多種小細節來實現屏幕適配。
如何理解使用dp為單位進行適配?:
但是,使用密度無關像素(dp)也不能做到適配所有屏幕!
2、造成誤差原因
在長期的Android發展過程中,由于Android設備的增多,Google制定的屏幕密度標準(mdpi、hdpi、ldpi等),在眾多廠家的生產過程中,已經被打破,人們沒有生產數完全符合屏幕密度標準的Android設備,對于真實手機的屏幕密度值,是在Google標準的周圍浮動變化的,但是不乏存在一些廠商生產的設備偏離Google的屏幕密度標準比較大,這個時候再使用dp作為單位就不能完完全全的完成適配操作!(dp只有在大家標準統一的情況下才有更好的發展)
在所有計算公式中存在誤差:在計算真實像素密度時運用了開方運算和除法運算,導致所得結果存在誤差。
理論計算造成的誤差:
在計算對角線上像素點個數時,我們使用勾股定理計算得出,但實則存在誤差:
若將像素長度當做1,分辨率指的是橫縱向上的1的個數,計算記過表示的是對角線上有多少個1,但理論上對角線上 根號2 的個數才是像素點的個數!
屏幕對角線并不會和像素對角線重合,使計算結果存在誤差。?
3、ldpi、mdpi、hdpi、xhdpi、xxhdpi的使用
官方截圖:?
4、使用wrap_content、match_parent、權重
要確保布局的靈活性并適應各種尺寸的屏幕,應使用 “wrap_content” 、“match_parent”和權重控制某些視圖組件的寬度和高度。
使用 “wrap_content”,系統就會將視圖的寬度或高度設置成所需的最小尺寸以適應視圖中的內容,而 “match_parent”(在低于 API 級別 8 的級別中稱為 “fill_parent”)則會展開組件以匹配其父視圖的尺寸。
如果使用 “wrap_content” 和 “match_parent” 尺寸值而不是硬編碼的尺寸,視圖就會相應地僅使用自身所需的空間或展開以填滿可用空間。此方法可讓布局正確適應各種屏幕尺寸和屏幕方向。
5、使用相對布局,不要使用絕對布局
我們大部分時候使用的都是線性布局、相對布局和幀布局,絕對布局由于適配性極差,所以極少使用。
關于布局的使用應該具體情況具體分析,在進行電視機頂盒的開發中就是使用的是絕對布局。
6、使用限定符進行適配操作
使用尺寸限定符——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、使用自動拉伸位圖
支持各種屏幕尺寸通常意味著您的圖片資源還必須能適應各種尺寸。例如,無論要應用到什么形狀的按鈕上,按鈕背景都必須能適應。
如果在可以更改尺寸的組件上使用了簡單的圖片,您很快就會發現顯示效果多少有些不太理想,因為系統會在運行時平均地拉伸或收縮您的圖片。解決方法為使用自動拉伸位圖,這是一種格式特殊的 PNG 文件,其中會指明可以拉伸以及不可以拉伸的區域。
.9的制作,實際上就是在原圖片上添加1px的邊界,然后按照我們的需求,把對應的位置設置成黑色線,系統就會根據我們的實際需求進行拉伸。
9、普通圖片處理
稍后會詳細介紹。
10、dimens使用
如上圖,我將市面上各分辨率下的屏幕尺寸,取了平均數,算出對應的真實的屏幕像素密度,與理論要求的屏幕像素密度作了對比,比值在倒數第二列。發現:(干貨要來了!)真實像素密度與理論像素密度的比值大致分為兩類,取其平均數,一類在1.15左右,另一類則在0.89左右。巧了,它們兩類正好各自對應w320dp和w360dp的寬度限定符!所以,dimens只需寫兩套即可(values-w320dp、values-w360dp),其name與真實數值的比值就是剛剛我們算出的兩個平均數! 以后我們就不需要對應各種分辨率寫多套dimens了,兩套dimens即可。
圖片處理
1、logo
logo需要36*36、48*48、72*72、96*96、144*144、192*192px,圖片使用正方形形狀,在某些機型上面,會自動顯示為圓角正方形;
Android8.0以后,系統增加了logo點擊效果和動畫,可按以上尺寸制作圓形logo,但圖片必須為正方形,圓形以外區域透明。
2、普通圖片
UI切圖只需按照720*1280,4.7寸屏幕切圖即可;
應為iphone6等分辨率、尺寸、像素密度都與要求接近,可使用IOS的2x圖代替。
3、純色圖、.9圖
純色按鈕或漸變按鈕可使用代碼設置顏色或.9圖實現,不必用圖片作為背景。
4、動畫、自定義view、shape
可以使用代碼進行控制和展示多種視圖,如patch動畫替代幀動畫。
5、ImageView的ScaleType
關于ScaleType請參考這里:http://blog.csdn.net/jiashuai94/article/details/77673625
其他
1、代碼適配
在代碼中使用Google提供的API對設備的屏幕寬度進行測量,然后按照需求進行設置。
幾個主要使用的API:
對于當前控件的寬高設置,需要做的操作是首先要獲取到該控件的父控件,使用父控件對當前控件的寬高進行設置操作!
API
DisplayMetrics metrics = new DisplayMetrics ();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
手機對應的寬高:
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);
在上面的兩個計算操作中最后加上0.5f的作用是:進行float強轉到int類型的時候會出現都是精度的問題。當使用Java代碼進行寬高設置的時候,假如出現320.2dp這樣的數據此時直接進行int得到的值是320;但是假如出現320.7這樣的數據的時候,由于int的計算規則,會直接強轉為320,但是從實際出發,這個時候的值取321更為合適。
所以在計算的最后直接加0.5,這樣一來,320.2+0.5=320.7,進行數據的強轉操作得到的數據是320,320.7+0.5=321.2,進行數據強轉操作得到的數據是321,這樣一來得到的數據就和實際預想的更為接近!!
2、接口配合
本地加載圖片前判斷手機分辨率或像素密度,向服務器請求對應級別圖片。