android dp sp px dpi dip density 之水落石出

android顯示的一些單位density dpi dp(dip) sp px及分辨率的概念,對於這些單位,還在一頭霧水?

Come On,就是這篇文章了。當然看懂了本篇,可以再看下這篇:點擊打開鏈接 ,瞭解android對於屏幕大小的規定及加載layout的參數影響。

這裏爲了防止每個概念都是動態的,我們把px固定,即出廠了的屏幕的像素點不會變了。(屏幕像素點大小:同樣的5寸屏幕,垃圾屏的像素點大,顯示模糊;好屏的像素點小,顯示精細)。

後面分析的前提條件都是同一塊手機屏幕,px是一個定值。

放大後,下面的一個個點,就是像素。



一、概念:

  • ScreenSize(屏幕尺寸)
    這個是指屏幕對角線的長度,後面計算的單位都是/inc,這個inc就是以屏幕尺寸爲基準(作爲除數)的來的。(盜圖不可恥)


  • Resolution(分辨率)
    是指屏幕的垂直和水平方向的像素數量,如果分辨率是 1920*1080 ,那就是垂直方向有 1920 個像素,水平方向有 1080 個像素。

  • Dpi(像素密度)
    是指屏幕上每英寸(1英寸 = 2.54 釐米)距離中有多少個像素點。常見的120、160、240、320、480等。
    dpi是dot per inch,每英寸多少點,ppi是 Pixel per inch,每英寸像素數,針對顯示器的設計時,dpi=ppi。ppi計算方法是長寬各自平方之和開方,除以對角線長度(單位英寸)。見下圖。

  • Density(密度)
    密度。常見取值1.5、1.0等 。和標準dpi的比例(標準dpi爲:160px/inc)。這個其實就是倍數:320dpi的density就是2.0)320/160),其餘density的取值,根據其dpi與標準dpi的比例值得到。

  • Dip / dp (設備獨立像素)
    也可以叫做dp,長度單位,同一個單位在不同的設備上有不同的顯示效果,具體效果根設備的密度有關(注意:跟密度有關)。

  • Px (Pixel像素)
    也稱爲圖像元素,是作爲圖像構成的基本單元。這裏簡單的認爲,一個屏幕出廠了,這個px就固定了。

概念有點蒙?沒關係,上圖(盜圖不可恥):


二、相互關係

從一部分的概念,基本就知道了dpi是有分辨率決定的,分辨率越高,dpi也就越大,沒有錯,是這樣的。

從上圖中可以看到主要的值:

屏幕尺寸:5inc、屏幕分辨率:1080x1920、dpi:440px/inc。dp放到後面在理解。

到此,基本就知道了,一塊屏幕出廠了,分辨率固定了,屏幕尺寸固定了,dpi也是固定的。

But,看到了問題:不同廠商的屏幕大小不一樣,分辨率不一樣,那不就有很多的density了嗎,很亂啊。

是的,so,google粑粑爲了解決這個問題, Android 中內置了幾個默認的 Dpi ,在特定的分辨率下自動調用,也可以手動在配置文件中修改,如下圖。


那麼問題來了,g粑粑固定了dpi,那和分辨率不就沒有直接換算的關係了嗎。是的,是的,是的,所以不小心就會出很多問題,比如cts問題,自定義圖片然後設置各種佈局的dp等等。

這些後面會講,這一部分就知道:實際上dpi是由分辨率計算的到的,dpi和分辨率是有關係的。But,google將其剝離開來了,手機中的dp,sp均以來dpi計算,包括dpi都和分辨率不在有毛線關係,只不過dpi的設置是參考分辨而選取設置的,不是精確計算的了。

三、分辨率固定,看下dpi、dp、sp、px的關係

先看一張圖:(分辨率720x1280,選的的density是320)


這張圖最上面是兩個320px的textview,正好鋪滿720px寬的屏幕。

下面一次是360dp和360sp的textview,也鋪滿了屏幕(後面會講sp--px及dp--px的關係)。

下面是一個.9圖片,最下面顯示的是當前手機的display的信息。

從上圖中看到320dp和320sp都充滿的720px的屏幕,也就是在dpi爲320的時候1dp=1sp=2px了(320/160=2,第一部分density概念介紹)。


dp和sp是根據dpi的變化而變化的值。看下google粑粑的換算:

    /**
     * Converts an unpacked complex data value holding a dimension to its final floating 
     * point value. The two parameters <var>unit</var> and <var>value</var>
     * are as in {@link #TYPE_DIMENSION}.
     *  
     * @param unit The unit to convert from.
     * @param value The value to apply the unit to.
     * @param metrics Current display metrics to use in the conversion -- 
     *                supplies display density and scaling information.
     * 
     * @return The complex floating point value multiplied by the appropriate 
     * metrics depending on its unit. 
     */
    public static float applyDimension(int unit, float value,
                                       DisplayMetrics metrics)
    {
        switch (unit) {
        case COMPLEX_UNIT_PX:
            return value;
        case COMPLEX_UNIT_DIP:
            return value * metrics.density;
        case COMPLEX_UNIT_SP:
            return value * metrics.scaledDensity;//A:這裏先忽略,scaledDensity默認和density是一樣的。
        case COMPLEX_UNIT_PT:
            return value * metrics.xdpi * (1.0f/72);
        case COMPLEX_UNIT_IN:
            return value * metrics.xdpi;
        case COMPLEX_UNIT_MM:
            return value * metrics.xdpi * (1.0f/25.4f);
        }
        return 0;
    }
從上面code:px是直接返回大小的,其他的值,需要轉換爲px再返回。

dip也就是dp是當前的值,乘以density;sp需要乘以scaledDensity的到px。

A點解釋:sp的換算爲什麼是個sacaled的density呢?在“seeting--顯示--字體大小”中,可以修改字體大小,這個值就是scaledDensity,如果默認的話,就是density,其他的則會個density乘以一個係數的到這個scaledDensity。這也就是爲啥設置字體大小之改變文字大小的原因(文字(TextView)單位一般都是sp)。


到此,基本高清了dp、sp、px三者依賴dpi的換算關係了。

再看兩張圖,加深下印象:


第一張圖是dpi是80,可以看到360dp的只佔180個像素(當前dpi/標準dpi:80/160=0.5);

第二張圖是dpi爲160,標準dpi,360dp就佔了360個像素。

同時這兩張和dpi=320的那張比,也可以看到.9圖片不一樣大了,這是因爲我使用了統一張.9圖片,如果,希望不同的density下,圖片顯示一樣大,就需要畫不同的圖片分當不同的文件夾下。google粑粑源碼中res下面分了很多個文件夾就是這個作用。



所以,在自定義圖片,佈局中,要注意在不同density手機上,是可能存在問題的。當遇到顯示問題的時候,可以先check下自己自定義佈局中的單位是否存在問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章