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);

方法二:

DisplayMetrics metrics=activity.getResources().getDisplayMetrics(); 

方法三:

Resources.getSystem().getDisplayMetrics();

下面再说下如何来获取屏幕的各个信息。

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以下的了。

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

如有任何问题,请及时与我联系,谢谢!

发布了135 篇原创文章 · 获赞 70 · 访问量 51万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章