1. 程式人生 > >android 中sp、dp、px的詳解

android 中sp、dp、px的詳解

轉載請註明出自flowsky37的部落格的部落格,尊重他人辛苦勞動!

在說sp、dp、px之前先說下解析度和畫素之間的關係,可能有的哥們不太清楚。我們經常說手機的解析度是1920*1080,或是其它的多少,那這個1080和1920到底指的是什麼呢?說這個又得要先說畫素,畫素是組成影象最基本的單元要素。解析度便是指在長和寬兩個方向上個擁有的畫素個數,一個畫素有多大就主要取決於顯示器的解析度,相同面積不同解析度的顯示屏,其畫素點的大小就不相同。

例如一個解析度為640*480的顯示屏,則表示在長的方向上有640個畫素點,寬的方向上有480個畫素點。總數就是640*480=307200(個畫素),簡稱30萬畫素。所以單位面積上畫素點越多即畫素點越小,這圖片就越清晰細膩。

還有一個螢幕畫素密度的計算,大家都知道手機螢幕的尺寸指的是對角線的長度,一般都是英寸為單位。那麼螢幕密度是怎麼計算呢?下面看一個例子:就拿小米4的屏吧,它的解析度是1920*1080。這兩個說了分別對應是常和寬方向上的畫素個數,根據勾股定理,就可以得出其對焦線的上的畫素個約為2202.907,除以螢幕5就可以得到畫素密度ppi為440.581。當然,小米肯定會四捨五入的宣稱自己手機螢幕畫素密度ppi為441。

回到正題,在android系統中,dp和dip是同一個東西,早期叫dip後來為了和sp統一,改成dp。英文名:devices independent pixes(裝置獨立畫素)。

px:pixels(畫素)。

sp:scaled pixes(放大畫素),在android中用於字型的設定。當然字型也可以用dp設定,但官方推薦用sp。

dp:也就是dip,device independent pixels(裝置獨立畫素)。不同裝置顯示的效果相同,與密度無關。規定如果螢幕密度為160時,dp、sp以及px之間的關係為:1px = 1sp = 1dp。如果拿px做單位的話,如果手機螢幕的尺寸不變,但是密度增大一倍的話,那px就得增大一倍。例如某手機密度為160,將一個控制元件的長度設為100px。如果手機的密度變為320,尺寸不變,還是設定空間的長度為100px,這時控制元件顯示會縮短一半,因為畫素點縮小了一倍。但是如果設定的單位為dp或者sp,就會根據手機螢幕的密度進行自動轉換,不用自己去考慮螢幕的密度,永遠是你設定的那個尺寸比例。

特別是在android中用canvas進行畫圖的時候,裡面用的尺寸單位是px,如果不轉換成dp的話,在不同的解析度手機上顯示的效果肯定是不一樣的。下面給出一個dp與px,以及sp與px相互轉換的工具類。

package com.bob.application.displaydensity;

import android.content.Context;

public class PixelsUtils {
    private Context context;

    public PixelsUtils(Context context) {
        this.context = context;
    }

    /**
     * @param pxValue 傳入的px的值
     *  px轉換為sp
     */
    public int pxTosp(float pxValue){
        final float scale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int)(pxValue/scale+0.5f);
    }

    /**
     *
     * @param spValue 傳入的sp的值。
     * sp轉換為px
     */
    public int spTopx(float spValue){
        final float scale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int)(spValue * scale + 0.5f);
    }

    /**
     *
     * @param pxValue   傳入的畫素值
     *  px轉換為dp
     */
    public int pxTodp(float pxValue){
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int)(pxValue / scale + 0.5f);
    }

    /**
     *
     * @param dpValue 傳入的dp的值
     *  dp轉換為px
     */
    public int dpTopx(float dpValue){
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int)(dpValue * scale + 0.5f);
    }
}

一般情況下在任何一臺手機列印scale的值是你會發現,context.getResources().getDisplayMetrics().density與context.getResources().getDisplayMetrics().scaledDensity 的值其實是一樣。有人可能就要問了,那sp和dp到底有什麼區別呢。其實大部分情況下他倆沒什麼區別,如果你手上有小米手機的話,你可以在設定裡找到一個設定字型顯示的選項,裡面有小號、預設、中號及大號的選擇。一般情況下,系統使用的是預設,當你將字型大小的選擇改動了的話,再列印scale的值,你會發現上面兩個方法的值不一樣了,這時候就體現出了sp和dp的區別了。scale我們俗稱為比例因子吧,此時的dp和sp的比例因子不一致了,那麼你之前寫好的佈局就會有問題了,顯示肯定是不成比例。
下面是三星A7手機預設時列印的情況:
三星A7
如果我在系統設定中將字型調整為更小一號時,結果為:
三星A7
看到變化了吧,如果我將系統字型調整比必預設的大時:
三星A7

我再將測試機換為紅米1,預設時設定時:
紅米1
很明顯的看出A7比紅米的解析度高。
當我把字型調整為小一號時:
紅米1
當字型調整為大一號時:
紅米1

前面說過大部分情況下dp和sp沒多大的區別,但是此時做了調整後,無論是紅米還是三星都很明顯的就看出了它們之間的區別。其實dp和sp的區別也主要體現這些方面。

有些哥們開發的時候可能會遇到自己寫的佈局在其它手機都好著,怎麼在某臺手機怎麼顯示就是不對,非常鬱悶。這時候你就看下是不是字型用的不是預設的,從而導致了顯示混亂。

上面是個人對dp、sp、px的一些理解,如果有不明白的,可以留言;如果某些地方有誤,非常歡迎指出,謝謝!**