1. 程式人生 > >android中dp和px的關係

android中dp和px的關係

關於android的dp和px的關係是我剛開始學習android的第一個知識點,不知不覺學安卓也有一年了,但是偶然間我發現我理解的dp和px的關係一直是錯的,真的是有一點搞笑,今天特意寫一篇部落格紀念一下這個我理解錯一年的知識點。
dp和px之間又有一個dpi作為橋樑,我們分別看看這三個屬性:

  • px:畫素點,比如1080*1920的螢幕,就是寬1080個畫素點和高1920個畫素點。
  • ppi: 畫素密度,這個概念挺好理解的就是螢幕每英寸的畫素數量,關於他的計算方法(以1080*1920的5英寸螢幕為例):螢幕的對角線畫素數/螢幕的尺寸 √(1080*1080+1920*1920)/5=441ppi。這也就意味著即使是相同解析度的手機尺寸不同ppi也會改變。
  • dpi:dpi和ppi很容易搞混,其實他們是完全不同的兩個東西,ppi有專門的公式計算,但是dpi沒有,至少我沒有找到,Android在規範中規定了不同的解析度對應的dpi值,一般有120、160、240、320、480幾個。例如1080*1920的解析度的dpi為480,這樣無論手機的尺寸為多大dpi是不會變的,該解析度下1dp=3px。當然凡事都有例外,谷歌的pixel2雖然是1080*1920但是他的dpi是420。(不懂谷歌在想什麼)。
  • dp(也叫dip)裝置無關畫素。關於dp的官方敘述為當螢幕每英寸有160個畫素時(也就是160dpi),dp與px等價的,1dp=1px。那麼當螢幕為240dpi時,1dp=(240/160)px=1.5px。也就是說dp和px的換算在於dpi這個值,計算的公式為:1dp=(螢幕的dpi/160)px,如果以我們的1080*1920的5英寸螢幕為例那就是1dp=(441/160)px=2.8px。

關於dp和px的概念就這麼多,還是很簡單的(我這是在打臉嗎),下面講一下衍生出的兩個問題:
1.手機螢幕dp最大值是多少?
這個是根據手機的畫素數和dpi計算得到,公式:畫素數/(dpi/160)
例如一個1080*1920的手機,他的寬度有1080個畫素點,dpi為480,根據公式可得:1080/(480/160)=360dp
同理長度:1920/(440/160)=640dp

2.dp和px的互相轉換?
這裡會用到我們在程式碼中可以獲取到的一個值:手機密度Density,其實他就是手機的畫素密度與基準的比值。 即畫素密度為160時Density為1,可以通過下面的方法獲取這個值:

float scale = context.getResources
().getDisplayMetrics().density;

dp值轉換為px值得方法為:
假設手機密度 :density = x,dp的值為y
由1dp = density px
可知ydp = yx px
所以結果為yx

px值轉換為dp值得方法為:
假設手機密度 :density = x,px的值為y
由1px = 1/density dp
可知 ypx = y/x dp
所以結果為y/x

public class DensityUtil {  

    /** 
     * 根據手機的解析度從 dp 的單位 轉成為 px(畫素) 
     */  
    public static int dip2px(Context context, float dpValue) {  
        final float scale = context.getResources().getDisplayMetrics().density;  
        return (int) (dpValue * scale + 0.5f);  
    }  

    /** 
     * 根據手機的解析度從 px(畫素) 的單位 轉成為 dp 
     */  
    public static int px2dip(Context context, float pxValue) {  
        final float scale = context.getResources().getDisplayMetrics().density;  
        return (int) (pxValue / scale + 0.5f);  
    }  
}  

至於為什麼要加0.5f?
因為在java中,強制轉換符把float轉換為int時,是直接丟掉小數部分的,加0.5f起到了四捨五入的作用,可以減小誤差。