-
一、获取系统必要信息。
1.屏幕分辨率
一般描述成屏幕的"宽x高”=AxB
通过如下adb命令行查看
➜ ~ adb shell
generic_x86:/ $ wm size
Physical size: 720x1280
2.屏幕密度
➜ ~ adb shell
255|generic_x86:/ $ wm density
Physical density: 320
密度类型 代表的分辨率(px) 屏幕像素密度(dpi)
低密度(ldpi) 240x320 120
中密度(mdpi) 320x480 160
高密度(hdpi) 480x800 240
超高密度(xhdpi) 720x1280 320
超超高密度(xxhdpi)1080x1920 480
可以通过Physical density 找到对应密度类型
3.获取系统版本api信息
generic_x86:/ $ getprop ro.build.version.sdk
28
-
二、适配规则
系统查找资源会找最符合要求的。
假设当前手机屏幕是hdpi,res目录下含有mdpi,hdpi,xhdpi,xxhdpi,但是hdpi目录下没有需要的图片,其他的目录下都包含,
首先是高dpi原则,也就是如果当前dpi下没有,那么就从更高dpi的目录下开始寻找,也就是xhdpi---》xxhdpi---》mdpi。按hdpi进行按密度比例进行缩放。
-
三、适配方案
以values文件夹为例(适用drawable,layout,color等等)
values + - ldpi/mdpi/hdpi/xhdpi/xxhdpi/xxxdpi //区分不同屏幕密度的
values + - swXXXp //根据最小宽度来区分
values + - AAAxBBB //指定分辨率来区分
values + - en //指定语言来区分
values + - v24 //通过系统等级来区分
values + - land/port //通过横竖屏来区分
多个参数可以组合使用
例如:
values-en-sw600p-land-mdpi-v21
-
四、限定符优先级
限定符 | 示例 | 含义 | 优先级 | since version |
---|---|---|---|---|
MCC 和 MNC | 示例: mcc310 mcc310-mnc004 mcc208-mnc00 ... | 移动国家代码 (MCC),(可选)后跟设备 SIM 卡中的移动网络代码 (MNC)。 例如,mcc310 是指美国的任一运营商,mcc310-mnc004 是指美国的 Verizon 公司,mcc208-mnc00 是指法国的 Orange 公司。 | 高 | API 1 |
语言和区域 | 示例: en fr en-rUS ... | 语言通过由两个字母组成的 ISO 639-1 语言代码定义,可以选择后跟两个字母组成的 ISO 3166-1-alpha-2 区域码(前带小写字母“r”)。 这些代码不区分大小写;r前缀用于区分区域码。不能单独指定区域。 | ↓ | API 1 |
布局方向 | ldrtl ldltr | 应用的布局方向。 ldrtl 是指“布局方向从右到左”; ldltr 是指“布局方向从左到右”,这是默认的隐式值。 | ↓ | API17 |
最小宽度 | swdp 示例: sw320dp sw360dp ... | 限定资源仅适用于最小屏幕宽度为Ndp的手机(不考虑屏幕方向)。 比如1080x1920 480ppi的手机,最小宽度限定符就是sw360dp; 720x1280 320ppi的手机,最小宽度限定符也是sw360dp。 | ↓ | API 13 |
可用宽度 | wdp 示例: w320dp ... | 限定资源仅适用于最小可用屏幕宽度为Ndp的手机(考虑屏幕方向)。 一般情况下,该限定符的值与swdp相同。 | ↓ | API 13 |
可用高度 | hdp 示例: h655dp ... | 限定资源仅适用于最小可用屏幕高度为Ndp的手机(考虑屏幕方向)。 计算N的时候必须减去StatusBar和NavigationBar的高度。 比如1080x2160 480ppi的手机,若StatusBar高度为25dp,NavigationBar高度为40dp,则N = 720 - 25 - 40 = 655,即可用高度限定符为h655dp。 | ↓ | API 13 |
屏幕尺寸 | small normal large xlarge | small:QVGA,320x426(dp) normal:HVGA,320x470(dp) large:VGA,480x640(dp) xlarge:720x960(dp)【API 9】 | ↓ | API 4 |
屏幕纵横比 | nong notlong | long:宽屏,如 WQVGA、WVGA、FWVGA notlong:非宽屏,如 QVGA、HVGA 和 VGA 完全基于屏幕的纵横比(宽屏较宽),与屏幕方向无关。 | ↓ | API 4 |
圆形屏幕 | round notround | round:圆形屏幕,例如圆形可穿戴式设备 notround:方形屏幕,例如手机或平板电脑 | ↓ | API 23 |
屏幕方向 | port land | port:竖屏 land:横屏 | ↓ | API 1 |
UI 模式 | car desk television appliance watch | car:设备正在车载手机座上显示 desk:设备正在桌面手机座上显示 television:设备正在电视上显示,为用户提供“十英尺”体验,其 UI 位于远离用户的大屏幕上,主要面向方向键或其他非指针式交互【API 13】 appliance:设备用作不带显示屏的装置 watch:设备配有显示屏,戴在手腕上【API 20】 | ↓ | API 8 |
夜间模式 | night notnight | night:晚上 notnight:白天 | ↓ | API 8 |
屏幕像素密度 (dpi) | ldpi mdpi hdpi xhdpi xxhdpi xxxhdpi nodpi tvdpi anydpi | ldpi:120dpi mdpi: 160dpi hdpi:240dpi xhdpi:320dpi【API 8】 xxhdpi:480dpi【API 16】 xxxhdpi:640dpi【API 18】 nodpi:放不想缩放的位图 tvdpi:213dpi【API 13】 anydpi:此限定符适合所有屏幕密度,其优先级高于其他限定符。 这对于矢量可绘制对象很有用。【API 21】 六个主要密度之间的缩放比为 3:4:6:8:12:16(忽略 tvdpi 密度)。因此,9x9 (ldpi) 位图相当于 12x12 (mdpi)、18x18 (hdpi)、24x24 (xhdpi) 位图,依此类推。 如果您认为图像资源在电视或其他某些设备上呈现的效果不够好,而想尝试使用 tvdpi 资源,则缩放比例为 1.33*mdpi。例如,mdpi 屏幕的 100px x 100px 图像应该相当于 tvdpi 的133px x 133px。 | ↓ | API 1 |
触摸屏类型 | notouch finger | notouch:有触摸屏 finger:设备有一个专供用户通过手指直接与其交互的触摸屏 | ↓ | API 1 |
键盘可用性 | keysexposed keyshidden keyssoft | keysexposed:设备具有可用的键盘。如果设备启用了软键盘(不无可能),那么即使硬键盘没有展示给用户,哪怕设备没有硬键盘,也可以使用此限定符。 如果没有提供或已经禁用软键盘,则只有在显示硬键盘时才会使用此限定符。 keyshidden:设备具有可用的硬键盘,但它处于隐藏状态,且设备没有启用软键盘。 keyssoft:设备已经启用软键盘(无论是否可见)。 如果提供了 keysexposed 资源,但未提供 keyssoft 资源,那么只要系统已经启用软键盘,就会使用 keysexposed 资源,而不考虑键盘是否可见。 | ↓ | API 1 |
主要文本输入法 | nokeys qwerty 12keys | nokeys:设备没有用于文本输入的硬按键。 qwerty:设备具有标准硬键盘(无论是否对用户可见)。 12key:设备具有 12 键硬键盘(无论是否对用户可见)。 | ↓ | API 1 |
导航键可用性 | navexposed navhidden | navexposed:导航键可供用户使用。 navhidden:导航键不可用(例如,位于密封盖子后面)。 不知道指的啥,反正不是底部的虚拟按键。那玩意儿需要根据各个厂商的定制方案去适配(监听广播或者读数据库)。 | ↓ | API 1 |
主要非触摸导航方法 | nonav dpad trackball wheel | nonav:除了使用触摸屏以外,设备没有其他导航设施。 dpad:设备具有用于导航的方向键。 trackball:设备具有用于导航的轨迹球,如HTC G2。 wheel:设备具有用于导航的方向盘(不常见)。 | ↓ | API 1 |
平台版本(API 级别) | 示例: v3 v4 v7 ... | 从哪个版本开始支持此限定符 | 低 | API 1 |
-
五、限定符命名规则
1)可以同时使用多个限定符,用"-"连接。如values-sw360dp-h655dp-port;
2)不区分大小写;
3)同一类型的限定符只能出现一次;
4)限定符的使用顺序必须严格按照上表规定的优先级,否则会直接编译出错
-
六、限定符淘汰规则
1)假设res下存在以下目录: drawable/ drawable-en/ drawable-fr-rCA/ drawable-en-port/ drawable-en-notouch-12key/ drawable-port-ldpi/ drawable-port-notouch-12key/
2)用户手机的配置是: 语言区域 = en-GB 屏幕方向 = port 屏幕像素密度 = hdpi 触摸屏类型 = notouch 主要文本输入法 = 12key
那么该手机最终会采用哪个文件夹下的资源呢?
-
淘汰与设备配置冲突的资源文件: drawable/ drawable-en/
drawable-fr-rCA/drawable-en-port/ drawable-en-notouch-12key/ drawable-port-ldpi/ drawable-port-notouch-12key/ -
查表,从最高优先级(MCC)开始,若该限定符存在,则淘汰其它所有不含此限定符的文件夹,否则顺位取下一个优先级的限定符,本例先淘汰非en文件夹(en-GB > port > hdpi > notouch > 12key):
drawable/drawable-en/ drawable-en-port/ drawable-en-notouch-12key/drawable-port-ldpi/drawable-port-notouch-12key/ -
继续淘汰非port文件夹:
drawable-en/drawable-en-port/drawable-en-notouch-12key/
仅剩一个文件夹了!所以该手机采用的就是 drawable-en-port 下的资源!
-
七、适配提示
1) 在layout文件中设置控件尺寸时应采用fill_parent、wrap_content、match_parent和dp;
具体来说,设置view的属性android:layout_width和android:layout_height的值时,wrap_content,match_parent或dp比px更好,文字大小应该使用sp来定义。
2) 在程序的代码中不要出现具体的像素值,在dimens.xml中定义;
为了使代码简单,android内部使用pix为单位表示控件的尺寸,但这是基于当前屏幕基础上的。为了适应多种屏幕,android建议开发者不要使用具体的像素来表示控件尺寸。
3) 不使用AbsoluteLayout(android1.5已废弃) ,可以使用RelativeLayout替代;(使用ConstraintLayout更丰富的布局方式有效较少层级,非必须布局使用viewstub效率更高)
4) 对不同的屏幕提供合适大小的图片。
5) 使用9-patch PNG图片,svg矢量图能有效较少资源大小。
6)对图片资源进行压缩 网页工具https://tinypng.com/
7)分渠道打包保留一份最合适资源,有效较少应用包大小。
8)android studio去除无用资源
打开AS,点击工具栏的Analyze->Run Inspection by Name->输入unused resources->选择要搜索的范围回车→查看搜索结果并删除无用的资源文件。
9)百分比布局(比较适用于分辨率不同但比例一致)可以参考https://github.com/JulienGenoud/android-percent-support-lib-sample
10)微信资源混淆压缩方案 可以参考 https://github.com/shwenzhang/AndResGuard (名称会混淆,对按名字对应的皮肤方案有影响)