屏幕适配多个dimens

来源:互联网 发布:火箭队实力 知乎 编辑:程序博客网 时间:2024/05/18 01:03

由于Android手机屏幕的各异,导致我们在开发过程中,为保证ui效果的统一,往往需要针对性的进行屏幕适配。


我们先看几个概念:

px:pixel,像素Android原生API,UI设计计量单位,如获取屏幕宽高。

屏幕分辨率:指在纵向和横向方向上的像素点数,单位是px,一般显示方式是纵向像素数量*横向像素数量,如1920*1080。

屏幕尺寸:一般是屏幕对角线长度,单位是英寸,常见尺寸有3.5,4.0,4.3,4.7,5.0,6.0等。

屏幕像素密度:ppi pixel per inch的缩写,意思是每英寸屏幕上的像素数,因为屏幕尺寸是商家生产时就规定好的,屏幕尺寸一样的手机,屏幕宽高却不一定一样,所以通常取屏幕对角线像素数量和屏幕尺寸(屏幕对角线长度)来计算屏幕像素密度,计算公式就是通过勾股定理和分辨率计算得到屏幕对角线像素数量,再除以屏幕尺寸。手机参数上也会有这个数值。

dpi:dot per inch点像素密度,它的计算方法也和ppi一样,但从很多方面上,dpi是和ppi有区别的,ppi是用在设备上的单位,比如显示器;而dpi是用在印刷品上的单位,比如要打印一幅地图;在图像上的像素看起来是一个个点或者方块,这时候通常就将两者混用。要注意的是,我们并不能在Android适配时直接使用手机参数上的ppi值,而是使用dpi,Android对dpi根据大小做了规定的分档,以160dpi为基准,分为ldpi(120dpi)、mdpi(160dpi)、hdpi(240dpi)、xhdpi(320dpi)、xxhdpi(480dpi)等,当然现在手机的分辨率和尺寸更加多,像560dpi,600dpi也有,举个例子,Nexus 6 ppi是493,那按道理我们计算出来的dpi也是493,但Android的分档里面并没有493dpi,所以实际上它的dpi是560,而这个值我们是可以在手机的系统文件里面修改的。一定程度上,我们甚至可以说分辨率和适配没有关系,我们需要考虑的是dpi值,而这个值是可以与分辨率没有关系的,是手机厂家设的。



density 屏幕密度

densityDpi 屏幕密度dpi(dots per inch 每英寸包含像素个数)

scaledDensity 
    /**     * A scaling factor for fonts displayed on the display.  This is the same     * as {@link #density}, except that it may be adjusted in smaller     * increments at runtime based on a user preference for the font size.     */    public float scaledDensity;
scaleDensity和Density基本一致,不同的是它会在运行时根据用户系统设定的字体大小进行缓慢(小幅度)的调整


heightPixels 屏幕高度(像素)

widthPixels 屏幕宽度(像素)


通过设置多个dimens适配

比如values-w320dp,values-w360dp

通过上面的例子得到对应的dp值为360,

     wdp  = widthPixels / density


附dp和px互转:

TypeValue

    /**     * Converts a complex data value holding a dimension to its final value     * as an integer pixel size.  This is the same as     * {@link #complexToDimension}, except the raw floating point value is     * converted to an integer (pixel) value for use as a size.  A size     * conversion involves rounding the base value, and ensuring that a     * non-zero base value is at least one pixel in size.     * The given <var>data</var> must be structured as a      * {@link #TYPE_DIMENSION}.     *       * @param data A complex data value holding a unit, magnitude, and      *             mantissa.     * @param metrics Current display metrics to use in the conversion --      *                supplies display density and scaling information.     *      * @return The number of pixels specified by the data and its desired     * multiplier and units.     */    public static int complexToDimensionPixelSize(int data,            DisplayMetrics metrics)    {        final float value = complexToFloat(data);        final float f = applyDimension(                (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK,                value,                metrics);        final int res = (int)(f+0.5f);        if (res != 0) return res;        if (value == 0) return 0;        if (value > 0) return 1;        return -1;    }

TypedArray

    /**     * Retrieve a dimensional unit attribute at <var>index</var> for use     * as a size in raw pixels.  This is the same as     * {@link #getDimension}, except the returned value is converted to     * integer pixels for use as a size.  A size conversion involves     * rounding the base value, and ensuring that a non-zero base value     * is at least one pixel in size.     *     * @param index Index of attribute to retrieve.     * @param defValue Value to return if the attribute is not defined or     *                 not a resource.     *     * @return Attribute dimension value multiplied by the appropriate     * metric and truncated to integer pixels, or defValue if not defined.     *     * @see #getDimension     * @see #getDimensionPixelOffset     */    public int getDimensionPixelSize(int index, int defValue) {        if (mRecycled) {            throw new RuntimeException("Cannot make calls to a recycled instance!");        }        index *= AssetManager.STYLE_NUM_ENTRIES;        final int[] data = mData;        final int type = data[index+AssetManager.STYLE_TYPE];        if (type == TypedValue.TYPE_NULL) {            return defValue;        } else if (type == TypedValue.TYPE_DIMENSION) {            return TypedValue.complexToDimensionPixelSize(                data[index+AssetManager.STYLE_DATA], mMetrics);        } else if (type == TypedValue.TYPE_ATTRIBUTE) {            throw new RuntimeException("Failed to resolve attribute at index " + index);        }        throw new UnsupportedOperationException("Can't convert to dimension: type=0x"                + Integer.toHexString(type));    }