Android屏幕适配问题,dip,px,dpi,ppi,sp,density,分辨率,尺寸详细解释及转换

来源:互联网 发布:世界地图gis数据 编辑:程序博客网 时间:2024/06/06 01:32

一.概念解释

1.dip:

dip也简称dp,官方的解释是device independent pixels:设备无关像素,意思是在不同分辨率,尺寸的设备上的效果是一样的,待会会解释原因

2.px:

px即pixel的缩写,在我们手机上呈现的一条线,一个面,一张图像都是由最小的单位像素来表示的,如下图

3.分辨率:

分辨率的单位是px,表示一个设备在横纵方向上的像素点的数量,例如很多手机的像素是1920×1080px,注意看这里的单位就是px

4.屏幕尺寸:

常见的屏幕尺寸有5.5,6单位是英寸(inch),表示的是手机的对角线的长度

5.ppi:

每英寸所拥有的像素点的数量(pixels per inch),可以根据勾股定理求出对角线的像素数量,然后除以尺寸

6.dpi:

(Dot Per Inch)每英寸所拥有的物理点数量,可以看成人为的把一个手机的物理尺寸分成每英寸多少个点。

7.sp:

(Scaled Pixels)与密度和字体缩放度无关的像素,与dp类似,但是可以根据用户的字体大小首选项进行缩放

8.metrics.density:

从字面上的意思来说是“密度”,不过它不等于像素密度,也不等于dpi

提供手机屏幕配置图片一张,对照以上学习

二.关系以及转换

什么叫密度?

Android 中的密度就是屏幕每英
寸所包含的像素数,通常以 dpi为单位。比如一个手机屏幕的宽是 2 英寸长是 3 英寸,如果
它的分辨率是 320*480 像素,那这个屏幕的密度就是 160dpi,如果它的分辨率是 640*960,
那这个屏幕的密度就是 320dpi,因此密度值越高的屏幕显示的效果就越精细

1.dpi和ppi的关系

dpi是物理上的,即人为的划分每英寸上面有多少个点,但是这个物理点到底多长,需要多少个像素点去填这个并不固定,ppi是图像上的,即每英寸有多少个像素点


注意在android中dpi所指的概念就是图像上的ppi

dpi最早是用于印刷行业,跟ppi还是有本质不同的,Android应该是误用了dpi这个概念。但是在android中我们认为dpi就等于ppi就可以了

谷歌把160ppi的屏幕规定有160dpi,即一个物理点对应一个像素点,所以现在160这个值是固定的了

二.px和dp的转换

metrics.density = dpi/160

这其中dpi和160的单位都是(像素/英寸),所以metrics.density根本没有单位只是一个比值,用来描述dp和px的关系,

1px = metrics.density * 1dp

说到这里,sp和px的关系也就不用解释了,和dp与px的关系类似

三.实例

1.textView.setTextSize()这个方法默认接收的值的单位sp

按住ctrl+左键点击方法就可以进入看源码了,进去后我们发现它调用了一个重载方法,多了个参数TypedValue.COMPLEX_UNIT_SP

public void setTextSize(float size) {        setTextSize(TypedValue.COMPLEX_UNIT_SP, size);    }

然后再点进去看

public void setTextSize(int unit, float size) {        Context c = getContext();        Resources r;        if (c == null)            r = Resources.getSystem();        else            r = c.getResources();        setRawTextSize(TypedValue.applyDimension(                unit, size, r.getDisplayMetrics()));    }

最终调用的是applyDimension这个方法,我们再看

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

这个方法中unit是单位的意思,用来表明你传入的是什么单位的值,针对unit的取值做了不同的事,以unit值为COMPLEX_UNIT_SP为例,最终返回的是value * metrics.scaledDensity,这里的metrics.scaledDensity就是之前说过的metrics.density,px和sp的比值,所以这个方法内部最终把我们传入的sp转换成了px,这就说明了真正渲染图片所用的尺寸单位还是px,sp和dp只是个方便使用的虚拟单位

2.以LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(int width, int height)为例,所有的Params构造需要传入的宽高参数单位都是px,为了屏幕适配的更好,这里需要我们在传入之前把它转换为dp,为了四舍五入,在实际手动转换当中的公式是px = dp×density +0.5f× (dp>=0?1:-1)

0 0