参考自 https://blog.csdn.net/jiashuai94/article/details/77639511
一、为什么要适配
由于Android系统的开放性,任何用户、开发者、硬件厂商、运营商都可以对Android系统和硬件进行定制,修改成他们想要的样子。
但是这种“碎片化”到达什么程度呢?
以上每一个矩形都代表一种机型,且它们屏幕尺寸、屏幕分辨率大相径庭。随着Android设备的增多,设备碎片化、品牌碎片化、系统碎片化、屏幕碎片化的程度也在不断加深。
为了让我们的Android应用在各式各样的手机上运行的时候,能够保持界面效果一直,所以,我们需要对各种手机屏幕进行适配!
二、相关概念
屏幕尺寸(inch):
不论是电视、平板,还是手机,所说的屏幕尺寸是指 屏幕对角线的长度,单位是英寸(inch),1 英寸相当于 2.54 厘米;
即:1 inch ≈ 2.54 cm
屏幕分辨率之 px
屏幕分辨率指 设备屏幕上的像素个数,每个像素点的边长为 1px,其是组成手机屏幕的最小单位。
常说的手机分辨率为 1920*1080,即手机横向有 1080 个像素点,竖向有 1920 个像素点。屏幕尺寸一样的情况下,分辨率越高,显示效果就越精细和细腻。
注:在 Android 开发中,涉及与 View 尺寸(宽高)、位置(坐标)相关的数据,最终都是以 px 为单位进行度量和绘制的。
像素密度 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的计算公式:
首先要明确的一点是,ppi和dpi并不一定相等,这里我举出两个例子来证明:
三星 S6
- 屏幕尺寸:5.1英寸
- 分辨率:2560x1600
- ppi(根据上图计算方法):591
- dpi(取手机中的densityDpi):640
- density:4
一加6
- 屏幕尺寸:6.28英寸
- 分辨率:2280x1080
- ppi(根据上图计算方法):401
- dpi(取手机中的densityDpi):420
- density:2.65
density
density,其实是 DPI / (160像素/英寸) ,可以看出,DPI本身的单位也是(像素/英寸),所以density其实是没单位的,他就是一个比例值。
dp 与 px的换算
我们写布局的时候,肯定还是要知道1个dp到底有多少px的。
换算公式如下: dp = (DPI/(160像素/英寸))px = density px
即:px = density * dp
H, XH, XXH
在开发中涉及图片资源时,为了适配屏幕,我们经常会在不同的 drawable 目录下各放置一套资源,这样在不同 dpi 的设备上,对程序进行编码时,会使用对应 drawable 目录下的资源。以下是对照表(顺便整合 dp 与 px 的换算):
三、如何适配
适配误区
在进行适配的时候,人们总是关注于:代码、Layout、Dimens、图片、权重,这几种适配方式并不是屏幕适配的全部方案,除此之外还存在多种小细节来实现屏幕适配。
如何理解使用dp为单位进行适配?:
但是,使用密度无关像素(dp)也不能做到适配所有屏幕!
造成误差原因
在长期的Android发展过程中,由于Android设备的增多,Google制定的屏幕密度标准(mdpi、hdpi、ldpi等),在众多厂家的生产过程中,已经被打破,人们没有生产出完全符合屏幕密度标准的Android设备,对于真实手机的屏幕密度值,是在Google标准的周围浮动变化的,但是不乏存在一些厂商生产的设备偏离Google的屏幕密度标准比较大,这个时候再使用dp作为单位就不能完完全全的完成适配操作!(dp只有在大家标准统一的情况下才有更好的发展)
在所有计算公式中存在误差:在计算真实像素密度时运用了开方运算和除法运算,导致所得结果存在误差。
理论计算造成的误差:
在计算对角线上像素点个数时,我们使用勾股定理计算得出,但实则存在误差:
- 若将像素长度当做1,分辨率指的是横纵向上的1的个数,计算记过表示的是对角线上有多少个1,但理论上对角线上 根号2 的个数才是像素点的个数!
-
屏幕对角线并不会和像素对角线重合,使计算结果存在误差。
ldpi、mdpi、hdpi、xhdpi、xxhdpi的使用
使用wrap_content、match_parent、权重
要确保布局的灵活性并适应各种尺寸的屏幕,应使用 “wrap_content” 、“match_parent”和权重控制某些视图组件的宽度和高度。
使用 “wrap_content”,系统就会将视图的宽度或高度设置成所需的最小尺寸以适应视图中的内容,而 “match_parent”(在低于 API 级别 8 的级别中称为 “fill_parent”)则会展开组件以匹配其父视图的尺寸。
如果使用 “wrap_content” 和 “match_parent” 尺寸值而不是硬编码的尺寸,视图就会相应地仅使用自身所需的空间或展开以填满可用空间。此方法可让布局正确适应各种屏幕尺寸和屏幕方向。
使用自动拉伸位图
支持各种屏幕尺寸通常意味着您的图片资源还必须能适应各种尺寸。例如,无论要应用到什么形状的按钮上,按钮背景都必须能适应。
如果在可以更改尺寸的组件上使用了简单的图片,您很快就会发现显示效果多少有些不太理想,因为系统会在运行时平均地拉伸或收缩您的图片。解决方法为使用自动拉伸位图,这是一种格式特殊的 PNG 文件,其中会指明可以拉伸以及不可以拉伸的区域。
.9的制作,实际上就是在原图片上添加1px的边界,然后按照我们的需求,把对应的位置设置成黑色线,系统就会根据我们的实际需求进行拉伸。
四、图片处理
logo
![](https://upload-images.jianshu.io/upload_images/2157950-0d78c0b634418e1a.png?logo需要3636、4848、7272、9696、144144、192192px,图片使用正方形形状,在某些机型上面,会自动显示为圆角正方形; Android8.0以后,系统增加了logo点击效果和动画,可按以上尺寸制作圆形logo,但图片必须为正方形,圆形以外区域透明。