Android不同屏幕尺寸多分辨率适配

1、DisplayInfo{"内置屏幕", app 1280 x 672, real 1280 x 720, largest app 1280 x 1207, smallest app 720 x 647, 50.0 fps, rotation 0, density 160, 160.0 x 160.0 dpi, layerStack 0, type BUILT_IN, address null, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS}, 

DisplayMetrics{density=1.0, width=672, height=1280 , scaledDensity=1.0, xdpi=160.0, ydpi=160.0}, isValid=true}

2、DisplayInfo{"内置屏幕", app 1920 x 1080, real 1920 x 1080, largest app 1920 x 1870, smallest app 1080 x 1030, 60.000004 fps, rotation0, density 320 (159.89508 x 160.42105) dpi, layerStack 0, type BUILT_IN, address null, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS}, DisplayMetrics{density=2.0, width=1920, height=1080, scaledDensity=2.0, xdpi=159.89508, ydpi=160.42105}, isValid=true}

首先看以上两条信息的内容,以第一条为例解释下每个元素的意义:

DisplayInfo{

 " app 1280 x 672":是指当下可用的屏幕分辨率;

“real 1280 x 720”:是指真实的屏幕分辨率;

“largest app 1280 x 1207”:是指当前能支持的最大分辨率;

“smallest app 720 x 647”:是指当前能支持的最小分辨率;

“50.0 fps”:帧频,即屏幕每秒刷新次数;

“rotation 0”:转屏,0代表没有旋转;

“density 160(160.0 x 160.0)dpi”: density表示每英寸有多少个dp,它的单位是dpi:dot per inch ;

}

DisplayMetrics{

“density”:真实dpi(对角线打印点(dp)/对角线的英寸)与基准dpi(160)的比值;

 " width":是指当下可用的宽度;

“height”:是指当下可用的高度;

“scaledDensity”:字体缩放值;

“xdpi”:x轴方向上,每英寸的像素数;

“ydpi”:y轴方向上,每英寸的像素数;

}

       首先很容易看出 " app 1280 x 672"和“real 1280 x 720”的值并不相同,因为有些系统会有底部导航栏,通知栏等装饰组件占据屏幕,所以当系统有这些UI时会占据一部分屏幕,大概底部或者顶部各占25px左右,而 " app 1280 x 672"是指除去系统UI之外可用的屏幕,而“real 1280 x 720”是指包括系统UI在内的真实的屏幕分辨率。因此,在布局的时候,尽量在上下底边25px左右的边距的时候不要布功能组件。

     其次,有一个density 和scaledDensity,并且值相同,但测试时会发现有时候density 和scaledDensity的值并不相同,众所周知假如在xml里定义1dp=1dp时,如果density=2.0,那么最终得到的值会是2dp.那么看一下getDimensio方法,确认一下是不是(1dp)x(density)得到的2dp:

 getDimension方法的核心:

    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;

    }

由此方法可看出,dp的缩放值是density,而sp的缩放值是scaledDensity。

density我们知道是真实dpi与基准dpi的比值得来,那么scaledDensity是如何得来的呢?

scaledDensity的缩放与字体相关,而网上查资料说是sp的值跟用户系统偏好字体相关,那么查一下系统字体配置:

系统中对字体有如下配置,默认是Normal ,而且大部分机型并不支持用户修改字体,那么可以猜测scaledDensity 跟系统字号配置有关:
Small:0.9  
Normal:1.0  
Large:1.1  
Extra Large:1.15  

其中一般默认是1.0,那么scaledDensity=(字号)X(density).猜测是这样,并没有做验证测试。

了解完dp,sp,px的含义之后,再来看一下分辨率适配。

假定以base为基准分辨率:

==========================================

base:{

dpi=160;

尺寸=8x4.5;

分辨率=1280x720

}

此时 8 inch(英寸)=160dp*8

     8 inch(英寸)=160px*8

=========================================

参照1:{

dpi=320;

尺寸=8x4.5;

分辨率=1280x720

}

此时 8 英寸=320dp*8

     8 英寸=160px*8

也就是说,满屏的时候px值相同,dp值系统会自动缩放

=====================================================

参照2:{

dpi=160;

尺寸=16x9;

分辨率=1280x720

}

此时 16 英寸=160dp*16

     16 英寸=80px*16

也就是说,满屏的时候px值相同,dp值手动放大2倍

================================================

参照3:{

dpi=320;

尺寸=16x9;

分辨率=1280x720

}

此时 16 英寸=320dp*16

     16 英寸=80px*16

也就是说,满屏的时候px值相同,dp值系统放大2倍后再手动放大2倍

=======================================================

参照4:{

dpi=160;

尺寸=8x4.5;

分辨率=1920X1080

}

此时 8 英寸=160dp*8

     8 英寸=240px*8

也就是说,满屏的时候px值放大1.5倍,dp值不变

=======================================================

参照5:{

dpi=320;

尺寸=8x4.5;

分辨率=1920X1080

}

此时 8 英寸=320dp*8

     8 英寸=240px*8

也就是说,满屏的时候px值放大1.5倍,dp值系统自动缩放

=======================================================

参照6:{

dpi=160;

尺寸=16x9;

分辨率=1920X1080

}

此时 16 英寸=160dp*16

     16 英寸=120px*16

也就是说,满屏的时候px值放大1.5倍,dp值手动放大2倍

=======================================================

参照7:{

dpi=320;

尺寸=16x9;

分辨率=1920X1080

}

此时 16 英寸=320dp*16

     16 英寸=120px*16

也就是说,满屏的时候px值放大1.5倍,dp值系统缩放后再手动放大2倍

=======================================================

      从以上可以看出,当分辨率不变的时候,无论dpi与屏幕尺寸如何变化,px值不变,当分辨率变化时,目标px值=基准px*scale

    

。而以dp为单位的话,屏幕尺寸以及dpi的变化都会引起dp的变化。即影响px的因素只有分辨率,而影响dp的因素有dpi和屏幕尺寸。

因此,做多分辨率适配时,最简单精准的方法是以px为单位。

      当分辨率不同,但长宽比相同的时候,那么scaleW(目标宽/基准宽) 与scaleH(目标高/基准高)的值是相同的,那么scale很容易得出,即(目标宽/基准宽)。而当分辨率不同时,如果宽我们按照scaleW缩放,高按照scaleH缩放,那么图片会变形,文字也会在大小上产生偏差,如果我们按照基准长宽比缩放,那么图片和文字会保持不变,但是在一个2:1的的矩形屏幕上展示1:1的正方形ui,效果可能会有意想不到的变化。

     一般电视机上长宽比是4:3和16:9,假定基准长宽是16:9,目标长宽是16:12,那么scaleW=1,scaleH=1.33.如果我们采取等比例缩放,假如一个控件长度为16,高为9,用scaleW缩放后长度为16<=16,高为9<=12,用scaleH缩放后长度为21.28>16,高为11.97<=12,也就是说用scaleH会导致控件长度超出屏幕,因此等比例缩放时,scale取值为scaleW和scaleH中较小的一个。

      华数tv3.0+版本中,只适配1280x720和1920X1080两种分辨率,而且长宽比均为16:9,因此只需要两个在这两个包下

2930
1.6 KB


写两个dimens文件即可,字体与控件的单位均为px.

调用方法:

          xml中:

          代码中:

猜你喜欢

转载自blog.csdn.net/xiaobeizi1/article/details/86685542