天天看點

Android之px/dpi/dip/dp/density/DisplayMetrics和螢幕适配

Android之px/dpi/dip/dp/density/DisplayMetrics和螢幕适配

文章連結:http://blog.csdn.net/qq_16628781/article/details/69397950

友情連結:http://blog.csdn.net/qq_16628781/article/details/53488386

知識點

  1. px、DPI、density和dip/dp的簡介;
  2. Android系統設定的dpi和dp的關系+執行個體說明;
  3. layout_weight/權重/百分比适配布局;
  4. DisplayMetrics的說明及使用;
  5. 新名詞記錄{DisplayMetrics:描述螢幕密度、大小和字型縮放值等資訊的類;}

首先來幾個概念熱熱身。

螢幕尺寸:螢幕對角線的長度。不是很清楚為毛這麼量,可能是看起來更大吧。

分辨率:長和寬兩個方向有的像素點的乘積。例如當下最火的4k電視,那麼在寬上面有超過4千個像素點,高上面也有3千多個,那麼乘積就是120萬+的點來呈現畫面。手機同理。

px:就是長寬方向上的最小機關的一個發光點。

DPI:dots per inch。就是一英尺(約2.54平方)距離上面共有多少個像素點。

Density:一英尺(2.54* 2.54)面積距離上面共包含多少個像素點。例如,320 * 240的螢幕,那麼Dpi = 320 / 2 = 240 / 1.5 = 160。

dip/dp:Density independent pixels,裝置獨立像素。每個裝置可能都是不同的值。我們也用得最多。這裡重點用來了解。

Android預設的dpi

ldpi:分辨率:240x320;系統dpi:120;基準比例:120 / 160 = 0.75。

mdpi:分辨率:320x480;系統dpi:160;基準比例:160 / 160 = 1。

ldpi:分辨率:480x800;系統dpi:240;基準比例:240/ 160 = 1.5。

ldpi:分辨率:720x1280;系統dpi:320;基準比例:360 / 160 = 2。

ldpi:分辨率:1080x1920;系統dpi: 480;基準比例: 480 / 160 = 3。

看這麼多,蒙圈了吧?!舉個栗子?

這裡給一個例子來解釋一下。重複一下—dp/dip是和螢幕密度(DPI)無關的機關。

在1920 * 1080分辨率的手機上,預設就使用480的dpi。那麼我們的基準比例就是480/160=3。

例如我定義一個textview的

layout_width=” 200dp “,layout_height=”100dp”。

如果在1920 * 1080分辨率的裝置上,寬為:200 * 3 = 600px,600像素來顯示;高為:100 * 3 = 300px,300px來顯示。

但是,如果裝置螢幕是720px * 1280px的呢?那麼寬200dp * 100dp的就要400px * 200px來顯示。

如果裝置螢幕是480px * 800px,就需要300px * 150px來顯示。

如果裝置螢幕是320px * 480px,就需要200px * 150px來顯示。

如果裝置螢幕是240px * 320px,就需要150px * 75px來顯示。

是不是一目了然,上面的各個數學計算。

但是我在這裡弄一個比較極端的情況。假如我弄一個寬度為500dp * 400dp的TextView呢?那麼情況會是怎樣的呢?

這裡反過來,從小分辨率螢幕說起。

如果裝置螢幕240px * 320px,就需要375px * 300px來顯示。但是看到,裝置的螢幕就隻有240px寬,那麼就顯示不下了。

即使是1920 * 1080的裝置螢幕,也需要1500px * 1200px的來顯示,結果也是不能夠顯示滴。

那麼,這裡就引入一個問題:我應該如何來進行布局呢?或者說更好的螢幕适配?

如今,Android陣營的螢幕碎片化真的是太嚴重了,據不完全統計,Android裝置的螢幕有2萬多種,這是一個多麼可怕的資料。是以我們在開發的時候,就需要做螢幕的适配了,絕對不能夠布局的控件跑到螢幕外面去了,不然就鬧大了。

也許有童鞋就會說了,我按着最小的螢幕分辨率的來适配,那麼接着大的螢幕就完全可以裝下去了。這是一種解決方案。這并不能解決問題。這也許是在寬高隻有1至2個控件的基礎上。但是如果我的控件多到4,5,6個,那麼你還能過寫死每一個控件的寬度麼?如果寫死了,那麼在高分辨率的螢幕上看到的也許就隻占了一點點的寬度。這樣的布局就太難看了吧。

那麼如何來搞呢?如何更好地解決這個問題呢?

目前最推薦的方式是百分比(權重)布局,或者是layout_weight這個屬性。

注意:如果要使layout_weight生效,那麼在橫向的layout _width=”0dp”,或者在layout _height=”0dp”才能夠生效。

這個屬性的使用比較簡單:layout_weight值越大,對應的寬高就越大。我在這裡就不一一講解了。

DisplayMetrics類

DisplayMetrics類,是系統提供給我們的用以擷取裝置螢幕的一個API。系統推薦的用法:DisplayMetrics metrics = new DisplayMetrics();

getWindowManager().getDefaultDisplay().getMetrics(metrics);

方法一:

DisplayMetrics metrics = new DisplayMetrics();
Display display = activity.getWindowManager().getDefaultDisplay();
display.getMetrics(metrics);
           

方法二:

方法三:

下面再說下如何來擷取螢幕的各個資訊。

public static void getDisplayMetrics(Activity activity) {
        DisplayMetrics displayMetrics = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        float xdpi = displayMetrics.xdpi; //實體螢幕上x軸方向每英寸(2.54cm)的像素
        float ydpi = displayMetrics.ydpi; //y軸
        float density = displayMetrics.density; //螢幕密度,和像素px無關
        int densityDpi = displayMetrics.densityDpi; //沒英寸距離具有多少個像素點
        int heightPixels = displayMetrics.heightPixels; //螢幕的高度,機關為px
        int widthPixels = displayMetrics.widthPixels; //螢幕的寬度,機關為px
        float scaledDensity = displayMetrics.scaledDensity; //為字型适配的縮放機關,根據系統字型來縮放字型大小
        displayMetrics.setToDefaults(); //将上述值設定成預設值
//        displayMetrics1.setTo(displayMetrics2); //設定displayMetrics2的值複制到displayMetrics1中去
    }
           

可以根據自己的需要擷取相應的資訊即可。

其中densityDpi有3個取值,分别是DENSITY_ LOW = 120;DENSITY_ MEDIUM = 160;DENSITY_HIGH = 240;

總結

關于螢幕适配,我現在用的最多的也是“權重”/“百分比”/“layout_weight”來做,而且可以搜尋到,現在主流的機型都是4.5寸以上的了,或者說是5.0寸以上,對于某些4.5以下的螢幕,我們可以選擇性的放棄,不再要求适配。這裡的原因有不少,比如APP主打閱聽人為年輕人,那麼他們裝置的螢幕、性能和Android版本可能都是比較好的,那麼就可以不需要進行适配5.0以下的了。

适配的路子,任重而道遠啊,需要不停地努力向前。共勉

如有任何問題,請及時與我聯系,謝謝!