屏幕适配多个dimens

由于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值,而这个值是可以与分辨率没有关系的,是手机厂家设的。

屏幕适配多个dimens_第1张图片

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 data 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 index 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));
    }





你可能感兴趣的:(java)