android 屏幕dp值计算

来源:互联网 发布:淘宝网里的暗语解释 编辑:程序博客网 时间:2024/05/16 06:17

google从android 3.2版本之后使用sw**dp方式来进行多屏幕适配,那么屏幕的具体dp值多少?
为了确定设备屏幕的dp值,查找了些关于屏幕px,sp,dp值计算的资料。
这里呢,我把px2dp的方法贴出来以供大家参考:

/**         * 将px值转换为dip或dp值,保证尺寸大小不变         * @param context         * @param pxValue         * @return         */         public static int px2dip(Context context, float pxValue) {                 final float scale = context.getResources().getDisplayMetrics().density;                   return (int) (pxValue / scale + 0.5f);         }

公式也是蛮简单的。为了了解更多的内容信息,我这里呢查看了官方api的资料和源码资料来做参考。
开发安卓应用,总不免会遇到屏幕适配问题。google官方api也给我们讲了非常多的适配方法,其中谷歌采用dp值的屏幕宽高度量单位目的就是为了在尺寸相近的设备屏幕上展示相近的界面效果,并且按照屏幕的像素密度ppi划分了一些标准,以供开发人员适配,大家都知道在android工程的res中的drawable可以使ldpi,mdpi,hdpi,xhdpi等限令名来按屏幕适配,这些划分在源码中也能很容易的找到:
android源码中负责屏幕密度计算的类是DisplayMetrics。
在这个类的属性变量声明部分,我们看到了api中提到的屏幕密度分类(这里以android20版本源码作为参考,其他版本原理一致):

     public static final int DENSITY_LOW = 120;     public static final int DENSITY_MEDIUM = 160;     public static final int DENSITY_TV = 213;     public static final int DENSITY_HIGH = 240;     public static final int DENSITY_XHIGH = 320;     public static final int DENSITY_400 = 400;     public static final int DENSITY_XXHIGH = 480;     public static final int DENSITY_XXXHIGH = 640;     public static final int DENSITY_DEFAULT = DENSITY_MEDIUM;

注释说明部分过长就不贴了,有兴趣的朋友可以直接看源码。我们从上面这一段属性常量声明可以看到google将现有的安卓设备按照屏幕密度分为了以上的几个档。因为生产android设备厂家众多,各家的产品不尽是
上述的屏幕密度,也会有很多其他密度参数的设备。那么,很显然,我们按照上述几个档来计算宽高dp值的话也就顺理成章的成为了近似值(这也正是尺寸相同的屏幕适配上出现了布局偏差的主因)。
另外,我们看到最后的一个常量声明,从这里我们可以看出google是以160的mdpi作为标准密度值计算的。
那么,我们先来看看,DisplayMetrics到底能给我们拿回来什么数据,按照源码提供的该类的使用说明:

/** * A structure describing general information about a display, such as its * size, density, and font scaling. * <p>To access the DisplayMetrics members, initialize an object like this:</p> * <pre> DisplayMetrics metrics = new DisplayMetrics(); * getWindowManager().getDefaultDisplay().getMetrics(metrics);</pre> */

ok,DisplayMetrics 类说明直接告诉了我们使用方法:

DisplayMetrics mMetrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(mMetrics );Log.d(TAG, mMetrics.toString());

以我的手机为例,运行结果如下:

这里写图片描述

DisplayMetrics 的toString方法已经提供了很多有用信息包括了屏幕宽高的像素值,宽高的密度值以及一个密度比例值 density。
实际上,我们需要的数据已经都准备ok了,计算屏幕dp值直接就可以套用上面的px2dp值计算得出:
宽度dp值为:( int ) ( 1080 / 3.0 + 0.5f ) =360dp
高度dp值为:( int ) ( 1920 / 3.0 + 0.5f ) =640dp
我们继续研究为什么我的手机屏幕获取到的density是3.0。
我们查看源码关于density的注释已经可以明白:

     /**     * The logical density of the display.  This is a scaling factor for the     * Density Independent Pixel unit, where one DIP is one pixel on an     * approximately 160 dpi screen (for example a 240x320, 1.5"x2" screen),      * providing the baseline of the system's display. Thus on a 160dpi screen      * this density value will be 1; on a 120 dpi screen it would be .75; etc.     *       * <p>This value does not exactly follow the real screen size (as given by      * {@link #xdpi} and {@link #ydpi}, but rather is used to scale the size of     * the overall UI in steps based on gross changes in the display dpi.  For      * example, a 240x320 screen will have a density of 1 even if its width is      * 1.8", 1.3", etc. However, if the screen resolution is increased to      * 320x480 but the screen size remained 1.5"x2" then the density would be      * increased (probably to 1.5).     *     * @see #DENSITY_DEFAULT     */

这个关于density的注释说明已经说的很清楚,那么在源码中是怎么体现的呢:我们继续在源码中查找关于density的赋值位置:

    public void setToDefaults() {        widthPixels = 0;        heightPixels = 0;        density =  DENSITY_DEVICE / (float) DENSITY_DEFAULT;        densityDpi =  DENSITY_DEVICE;        scaledDensity = density;        xdpi = DENSITY_DEVICE;        ydpi = DENSITY_DEVICE;        noncompatWidthPixels = widthPixels;        noncompatHeightPixels = heightPixels;        noncompatDensity = density;        noncompatDensityDpi = densityDpi;        noncompatScaledDensity = scaledDensity;        noncompatXdpi = xdpi;        noncompatYdpi = ydpi;    }

我们在这个方法中不仅找到了关于density的赋值操作,还发现了scaledDensity ,xdpi和ydpi的赋值操作。
按照上面提到的源码中声明了DENSITY_DEFAULT,以160的mdpi作为基准密度来进行屏幕密度度量的。那么我的手机屏幕密度就是 160*3.0 = 480dpi。

0 0
原创粉丝点击