Screen的這些基本概念中,最重要的就是dip的理解,而理解dip就是理解android適配不一樣設備的關鍵。html
實際物理尺寸。就是咱們常說的3.5英寸屏幕,4.7英寸屏幕等等,這個長度說的是對角線的長度。在android中屏幕物理尺寸劃分爲這麼幾類:small,normal,large,extra large。下面是對尺寸以及密度的一個粗略分類。該圖可能會因爲實際設備尺寸和屏幕密度的不斷增長而更新,最新的請到官網查看。android
圖1express
「屏幕」分辨率,即屏幕上的像素總數。經常使用的表現形式如:1280x720, 1920x1080等。app
屏幕密度,與dpi表達的同一個意思,兩種不一樣的描述方式。官網如是說:ide
Screen density佈局
The quantity of pixels within a physical area of the screen; usually referred to as dpi (dots per inch). For example, a "low" density screen has fewer pixels within a given physical area, compared to a "normal" or "high" density screen.測試
public float density The logical density of the display.字體
public int densityDpi The screen density expressed as dots-per-inch.ui
但其實個人理解他就是一個縮放係數,具體緣由在後面解釋。按照屏幕密度全部的手機可被劃分爲如下幾類:ldpi (low,低密度), mdpi (medium,標準密度), hdpi (high,高密度), and xhdpi (extra high,超大密度)。
spa
每英寸像素數。與density描述的都是屏幕的密度。但請注意這個翻譯,實際上應該譯爲每英寸點數。爲說明緣由,不得不引入另外一個概念:PPI(Pixel per inch),每英寸像素數。實際PPI用於電腦顯示領域,DPI用於打印或印刷領域,但從好久以前兩個概念就已經開始混用:
「點」有時用來表示像素,特別是計算機市場,因爲計算機顯示器如LCD或CRT是由一個個極小的點來描繪圖像的,LCD顯示器在標準屏幕分辨率下,對於一個像素可認爲是由顯示器的一個「點」來顯示,所以ppi有時所寫爲DPI(dots per inch,每英寸點數)——維基百科:像素
到android這裏,乾脆就用dpi取代ppi表明像素密度。
像素密度=屏幕總像素數/屏幕大小。一般咱們知道屏幕的尺寸是諸如3.5英寸,5.0英寸等,這是對角線長度,咱們能夠先獲取對角線上的總像素數,再除以對角線長便可。
拿Mi2s舉例說明:4.3英寸,1280x720。對角線上像素值根據勾股定理可得√(1280^2+720^2)≈1468.6,接着1468.6/4.3≈341.5
然而,從代碼測試的結果看起來是有誤差的:
Density:2.0
DensityDpi:320
Resolution:1280x720
xDpi:345.0566 // x方向上(寬)每英寸像素數
yDpi:342.23157 // y方向上(高)每英寸像素數
能夠看出,xDpi≈yDpi≈341,與咱們的計算結果相近。但DensityDpi是320,爲何呢?在Screen Density中已經說過,android將全部屏幕的實際密度歸類,處在某個區間內的密度是個定值,參考下表:
密度分類 | DPI值(像素/英寸) | Density值 |
ldpi |
120 | 0.75 |
mdpi | 160 | 1 |
hdpi |
240 | 1.5 |
xhdpi |
320 | 2 |
xxhdpi |
480 | 3 |
表1
根據圖1種的分類,Mi2s的真實dpi爲341,341>300,因此Mi2s屬於xhdpi,再結合表1,得出DensityDpi=320。
從上面的數據也能夠看出Density和DensityDpi值不一樣,但規律是顯而易見的。在android中,mdpi是標準值,android將其density定爲1,以此爲準得出Density與DensityDpi的關係是:dpi=density*160。
個人疑問是,既然dpi能夠表明屏幕密度,還要density幹什麼?想要搞清楚該死的density,必需要結合dp,往下看。
獨立像素,虛擬單位,又稱設備無關像素。1dp的長度至關於一個160dpi的屏幕上一個物理像素的長度。而160dpi的屏幕則是被android定義爲基準的屏幕(mdpi)。在app運行的時候,android會將dp轉爲實際像素進行佈局。轉換的公式爲:px = dp * (dpi / 160)。
設想app將一張圖以像素爲單位進行佈局,該圖爲400px的正方形圖,當app運行在1920x1080上時看起來比較小,運行在960x640上時顯得很是的大,而咱們想要看到的效果是app運行在兩個手機上時這張圖看起來是大小相近的效果。
看下面這張圖是以px爲單位進行佈局的效果:
圖2
下面這張圖是使用dp佈局的效果:
圖3
想要達到這樣的效果,就須要在高密度手機上對其進行放大操做,低密度手機上對其進行縮小操做。可是咱們沒法預期本身的app會安裝在什麼密度,什麼尺寸的手機上,即便知道也不可能爲每一個手機準備一套圖,所以但願android能智能一些,我設置一個大概的尺寸,android能自動適配不一樣手機。因而就有了獨立像素這個單位。見名之意,開發人員只須要用dp或者直接使用wrap_content,剩下的交給android,系統會爲你的佈局和圖片作縮放。
那麼,android是如何創造出這個獨立像素的?
首先,咱們的思路是從原來用px進行佈局,改成用dp佈局,因爲最終dp仍是要轉化爲px,引入一個係數λ,則有:px=dp*λ,λ就是咱們的縮放係數;
其次,我最終目標是讓全部手機上看到的圖大小相同,那麼到底多大,是否是要有個標準,我就選一個定作標準,讓其餘不一樣密度的手機顯示的跟這個標準同樣大。那麼我把這個標準就定爲160像素/英寸吧,取個名字叫mdpi,接着把其餘密度的手機進行分類:ldpi(120像素/英寸),hdpi(240像素/英寸),xhdpi(320像素/英寸);
再次,歸類都歸好了,下面就開始縮放吧:
當app運行在標準手機上(mdpi),圖片應該不縮放,由於它是標準,即λ=1,此時px=dp;
當app運行在ldpi手機上時,因爲密度小於標準,圖像的長更長,寬更寬,爲了保持與標準相同的長寬,在ldpi上長要縮小原來的120/160=0.75,寬亦如此,即λ=0.75,此時px=0.75*dp;
當app運行在hdpi上時,λ=1.5,px=1.5*dp;
以此類推。。。
由上面的推導,其實λ=dpi/160=density,可見density就是λ。
1. 從官網的概念得知density與dpi都是描述屏幕密度的,彷佛是相同的概念,但何須用兩個同名概念來描述讓人混淆呢?我我的以爲何不把他們從命名上作個區分,density就是個縮放係數,dpi纔是對密度的準確描述。所以我只用dpi來表示屏幕密度,或像素密度,而density其實就是縮放係數,或密度係數;
2. 即便在某一個密度分組區間內(好比xhdpi)不一樣的密度的手機所展現的一樣大小的圖片,仔細看也不會徹底相同,畢竟他們的密度不一樣。所以android只是盡最大可能簡化適配的工做,分組並不能百分百解決適配的問題。
專用於android中的字體大小。sp產生的初衷與dp是相同的,只是它應用於字體大小。