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下自己自定义布局中的单位是否存在问题。

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