Android多屏幕尺寸适配原理

Html 字体大小单位 px em pt

网页上定义字体大小有常见三种单位,px、em、pt

px

px是pixel缩写,是基于像素的单位.在浏览网页过程中,屏幕上的文字、图片等会随屏幕的分辨率变化而变化,一个100px宽度大小的图片,在800×600分辨率下,要占屏幕宽度的1/8,但在1024×768下,则只占约1/10。所以如果在定义字体大小时,使用px作为单位,那一旦用户改变显示器分辨率从800到1024,用户实际看到的文字就要变“小”(自然长度单位),甚至会看不清,影响浏览。

em

em:即%,是相对单位,是一个相对长度单位,最初是指字母M的宽度,故名em。现指的是字符宽度的倍数,用法类似百分比,如:0.8em, 1.2em,2em等。通常1em=16px。,一般用来测量长度的通用单位(例如元素周转的页边空白和填充),当用于指定字体大小时,em单位是指父元素的字体大小。

在一个页面上给定了一个父元素的字体大小,这样就可以通过调整一个元素来成比例的改变所有元素大小.它可以自由缩放,比如用来制作可伸缩的样式表。

pt

PT是point(磅)缩写,是一种固定长度的度量单位,大小为1/72英寸。如果在web上使用pt做单位的文字,字体的大小在不同屏幕(同样分辨率)下一样,这样可能会对排版有影响,但在Word中使用pt相当方便。因为使用Word主要目的都不是为了屏幕浏览,而是输出打印。当打印到实体时,pt作为一个自然长度单位就方便实用了:比如Word中普通的文档都用“宋体 9pt”,标题用“黑体 16pt”等等,无论电脑怎么设置,打印出来永远就是这么大。

转换

浏览器的默认字体高都是16px,所以未经调整的浏览器在显示1em=16px,也就是说1px=0.0625em。为了简化font-size的换算,可以在css中的body中先全局声明font-size=62.5%,也就是定义了默认字体大小为16px*0.625=10px,子元素会继承父级元素的字体大小,于是1em=10px,所以12px=1.2em。px与em的转换通过10就可以得来。但是定义font-size=0.625em或者直接定义12px,这是没有效果的。链接

Android开发常见的尺寸单位

inch

英寸,1 英寸约等于2.54厘米,主要用来描述手机屏幕的大小。

DPI/PPI 

DPI = Dots Per Inch 

 PPI = Pixel Per Inch  

两个参数的区别就在于Dot和Pixel的区别,dot值的是显示器上每一个物理的点,而pixel指的是屏幕分辨率中的最小单位。这个两个难道会不一样么?会!当一个像素需要多于一个屏幕上的物理点来显示的时候dot就跟pixel不一样了。这个有另一个叫法叫做dppx(dot per pixel),即每个像素中有多少个点。大部分的显示器中一个像素即一个点,但目前一些比较好的屏幕和一些手机屏幕中dppx会大于1。比如说Mac Retina,iPhone,HTC One等。 相信大家都遇到过一些人的电脑屏幕,看上去总是那么傻大傻大的。就是因为他们把分辨率调的太低导致ppi变低了,让画面看上去那么的不协调。看下面两张图片,我在一个1366x768分辨率的显示器上把分辨率分别设置为1366x768和1024x768所显示的效果。 


 1024 x 768 


 1366 x 768  

但是大多是情况大家并不会把这两个名词分的那么清楚,所以如果这两个出现的时候基本上都表达的是同一个意思,即PPI(每英寸中有多少个像素)。 

PPI=屏幕对角线像素点数/屏幕对角线长度=( √ (屏幕横向像素点^2 + 屏幕纵向像素点^2)/对角线长度)

举例说明:若一款手机屏幕分辨率为720px*1280px,4.3英寸。则点密度为 √ (720^2 +1280^2) /4.3 = 342ppi。链接

分辨率 

分辨率这个词在很多地方都有,比如相机、视频、扫描仪。这里说的就是显示器的分辨率。显示器是由一个个像素点(pixel)所组成的,一般所说的显示器分辨率是1280x720就表示这个显示器水平方向有1280个像素,垂直方向上有720个像素。但是并非分辨率越高屏幕显示效果越好,还需要根据屏幕的大小来决定。也就是要看像素的密度(pixel density),这个指标就是DPI(Dots Per Inch)或者PPI(Pixels Per Inch),即英尺屏幕上像素或者是点的个数。

屏幕密度

手机的屏幕密度通常指的是手机屏幕的dpi(dots per inch),也就是每英寸的像素数。对于Android手机来说,常见的dpi有如下几种:

1. ldpi:对应的dpi范围为0 ~ 120,也就是说每英寸有0到120个像素点的屏幕的屏幕密度都属于ldpi

2. mdpi:dpi范围为120 ~ 160

3. hdpi:dpi范围为160 ~ 240

4. xhdpi:dpi范围为240~320

5. xxhdpi:dpi范围为320~480

6.xxxhdpi: dpi范围为480~560

在实际开发中,通常以dpi值120、160、240、320、480分别指代ldpi、mdpi、hdpi、xhdpi、xxhdpi。通常屏幕密度越大的手机显示的图像会越细腻。可以通过如下代码获取当前Android设备的屏幕密度:
private void getDpi() {DisplayMetrics dm = getResources().getDisplayMetrics();Log.i("TAG", "density = " + dm.density);Log.i("TAG", "densityDpi = " + dm.densityDpi);}复制代码

若我们在一台屏幕密度为320dpi的Android手机上运行以上代码,会得到如下输出:

density = 2densityDpi = 320复制代码

        上面输出中的densityDpi就是Android手机屏幕的dpi值,那么density是什么呢?实际上它代表的是当前屏幕的dpi值与基准dpi值的比值,这个基准dpi值为160。

dp(dip)

        Density-independent pixel, 是安卓开发用的长度单位,1dp表示在屏幕像素点密度为160ppi时1px长度。上面我们提到了选择dpi值160作为基准屏幕密度,这个基准屏幕密度人为建立起了dp与px间的关系:在dpi为160的Android设备上,1 dp = 1px。假设x为某UI控件以px为单位的大小,y为同一UI控件以dp为单位的大小,densityDpi表示屏幕密度,则x与y的关系为:x = y * densityDpi / 160 或者 x = y *  density据此,还可以计算出分辨率为1080x1920,屏幕密度为480dpi设备以dp为单位的宽高值,宽度:1080 / 3 = 360dp

高度:1920 / 3 = 640dp,我们在设计控件的宽度时要注意不能超过设备的最大宽度值。

sp

在介绍sp之前,我们先来一起看下TypedValue类中包含的一个用户将dp、sp等单位转换为px的静态方法:

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转换为px,会执行如下代码:

return value * metrics.density;复制代码

        density我们在前面介绍过,指的是当前dpi与基准dpi(160)的比值。density的计算方式就是当前屏幕的dpi除以160。也就是说,在屏幕的dpi为120、160、320、480时,density的值分别为0.75、1、2、3。
若要将sp转换为px,则会执行如下代码:

return value * metrics.scaledDensity;复制代码

        可以看到,sp转换为px的计算公式与dp转换为px时相似,那么scaledDensity是什么呢?实际上,scaledDensity不同于density,scaledDensity是可以动态改变的,当用户改变了Android设备的字体缩放比例时,scaledDensity的值就会发生变化。scaledDensity的计算公式为:scaledDensity = density * fontScale。其中fontScale代表用户设定的Android设备字体缩放比例,默认为1。也就是说,当用户没有改变Android设备的字体缩放比例时,sp、dp与px的换算是相同的。

在Android系统设置菜单中更改density、scaledDensity和分辨率

通常我们在给页面做UI适配时,会去找来很多台不同的Android设备,其实我们只需要到系统菜单中去设置density、scaledDensity和分辨率这些参数,然后就可以在一台Android设备上看到不同Android设备上的页面展示效果,以huawei mate8手机为例,进入到系统设置菜单显示条目:


通过ADB shell命令更改density和分辨率

在终端输入adb shell wm查看支持的命令集:


更改和查看density命令:


更改和查看分辨率命令:



转载于:https://juejin.im/post/5cf1fa70f265da1bb31c207e

猜你喜欢

转载自blog.csdn.net/weixin_33967071/article/details/91440586