android res 资源匹配目录 、 drawable与 mipmap的区别
在res目录下,有各种各样的资源文件目录,这些目录的名字是有规则的,为了更好的适配多种设备,我们需要了解这些目录的命名规则,及各中限定符的意义,熟悉系统匹配这些资源的规则。
-
给资源配置限定符
配置限定符是有顺序的,它的优先顺序如下(从高到低):(
res
下的全部资源)-
MCC和MNC
移动国家代码(MCC)和移动网络代码(MNC);
drawable-mcc310-mnc004
是指美国的 Verizon 公司; -
语言和区域
例如:
en
,fr
,fr-rFR
,fr-rCA
;drawbale-en
,drawable-fr
-
布局方向
ldrtl
:表示“布局方向从右到左”ldltr
:表示“布局方向从左到右”,这是默认的隐式值。layout
,layout-ar
(阿拉伯国家专配layout),layout-ldrtl
-
smallestWidth (新配置限定符, android 3.2引入)
sw<N>dp ,屏幕的基本尺寸
-
sw320dp
适用于
320*320 ldpi
、320*480 mdpi
、480*480 hdpi
-
sw600dp
适用于
600*1024mdpi
(7英寸的平板电脑) -
sw720dp
适用于
720*1280 mdpi
(10英寸平板电脑)
layout-sw320dp
,layout-sw720dp
... -
-
可用宽度(新配置限定符, android 3.2引入):
w<N>dp, w720dp, w1024dp
layout-w720dp
可用高度(新配置限定符, android 3.2引入):h<N>dp
-
屏幕尺寸:
small
,normal
,large
,xlarge
(后被抛弃)layout
,layout-large
... 屏幕纵横比:
long宽屏
、notlong 非宽屏
圆形屏幕:
round
,notround
屏幕方向:
port
垂直,land
横向UI模式:car, desk, television, appliance, watch
夜间模式: night, notnight
-
屏幕像素密度DPI: 现在常用的分类限定符
mdpi
、hdpi
、xhdpi
、xxhdpi
、xxxhdpi
drawable
,drawable-xhdpi
,drawable-mdpi
-
触摸屏类型
notouch
,finger
-
键盘可用性
keysexposed
: 设备具有可用的键盘;keysoft
: 设备启用软键盘; -
主要文本输入法
nokeys
:设备没有用于文本输入的硬按键;qwerty
:设备具有标准硬键盘(无论是否对用户可见);12key
:设备具有 12 键硬键盘(无论是否对用户可见); -
导航键可用性
navexposed
:导航键可供用户使用;navhidden
:导航键不可用(例如,位于密封盖子后面); -
主要非触摸导航方法
nonav:除了使用触摸屏以外,设备没有其他导航设施。
dpad:设备具有用于导航的方向键。
trackball:设备具有用于导航的轨迹球。
wheel:设备具有用于导航的方向盘(不常见)
-
平台版本(API 级别)
设备支持的 API 级别。例如,v1 对应于 API 级别 1(带有 Android 1.0 或更高版本系统的设备),v4 对应于 API 级别 4(带有 Android 1.6 或更高版本系统的设备).
-
-
屏幕密度
现在常用的属性是屏幕密度:
-
六种通用的密度:
ldpi(低): ~120 dpi 3
mdpi(中):120~160dpi 正常尺寸 4
hdpi(高):160~240dpi 6
xhdpi(超高):240~320dpi 8
xxhdpi(超超高):320~480dpi 12
-
xxxhdpi(超超超高):480~640dpi 16
只针对启动图标才需要提供xxxhdpi
注:最后一列为dpi之间的比例,用于转换。(例:如果
xhdpi
里不存在资源,可以从xxhdpi
中去同名id的资源,缩放0.66(8/12)即可)
-
-
匹配资源的实现逻辑:
系统通过以下过程确保任何给定资源(id)在当前屏幕上都能保持尽可能最佳的显示效果:
其实是对某一个具体的资源id进行匹配。
-
使用适当的资源
根据当前屏幕的尺寸和密度,使用应用中提供的任何尺寸和密度特定资源,寻找最佳匹配项。
-
如果没有匹配资源目录
系统将使用默认资源,并按需要向上 或向下扩展,以匹配当前的屏幕尺寸和密度。
注意: “默认”资源是指未标记配置限定符的资源。例如,
drawable/
中的资源是默认可绘制资源。 系统假设默认资源设计用于基线屏幕尺寸和密度,即 正常屏幕尺寸和中密度。 因此,系统对于高密度屏幕向上扩展默认密度 资源,对于低密度屏幕向下扩展。 -
存在资源目录在,但在目录中没有指定的资源,不一定会使用默认资源
系统在缩放时可能 改用其他密度特定资源提供更好的 效果。例如,查找低密度资源但该资源不可用时, 系统会缩小资源的高密度版本,因为 系统可轻松以 0.5 为系数将高密度资源缩小至低密度资源,与以 0.75 为系数 缩小中密度资源相比,伪影更少。
如果当前手机分辨率为drawable-xxhdpi,且没有发现对应的资源时,会优先去xxxhdpi去寻找, 接着向更高密度去寻找,没有后,在向下寻找,依次为:
drawable-xhdpi -> drawable-hdpi -> drawable-mdpi -> drawable-ldpi。
-
务必要为应用使用的每种资源类型提供默认资源,这关系到应用是否会发生crash。
android 如何查找最佳匹配资源
系统逻辑:
假设以下可绘制对象目录分别包含相同图像id的不同版本:
drawable/
drawable-en/
drawable-fr-rCA/
drawable-en-port/
drawable-en-notouch-12key/
drawable-port-ldpi/
drawable-port-notouch-12key/
而设备的配置如下:
语言区域 = en-GB
屏幕方向 = port
屏幕像素密度 = hdpi
触摸屏类型 = notouch
主要文本输入法 = 12key
逻辑规则如下:
-
淘汰所有与设备配置冲突的资源文件。
会去遍历所有的设备限定符,把所有冲突的限定符淘汰掉, 即全部的设备配置的限定符都会在这里被便遍历,淘汰掉与之冲突的资源文件
drawable-fr-rCA/ 目录与 en-GB 语言区域冲突,因而被淘汰。
注: 其他的设备限定符未与当前目录冲突,故而不淘汰。
剩余:
drawable/
drawable-en/
drawable-en-port/
drawable-en-notouch-12key/
drawable-port-ldpi/
drawable-port-notouch-12key/
例外:屏幕像素密度是唯一一个未因冲突而被淘汰的限定符。 尽管设备的屏幕密度为 hdpi,但是 drawable-port-ldpi/ 未被淘汰,因为此时每个屏幕密度均视为匹配。
这也表明要为除了dpi限定符之外的
资源id
提供默认的资源放入默认目录里,例如drawable,string下的资源id
, 不然会因找不到资源而发生crash
. -
选择列表(表 2)中(下一个)优先级最高的限定符。(先从 MCC 开始,然后下移。)
2,3,4步里是对同一个限定符做处理。处理完4后,经过5,若仍有多个资源目录,会再次返回2,处理下一个限定符。
-
是否有资源目录包括此限定符?
- 若无,请返回到第 2 步,看看下一个限定符。(在该示例中,除非达到语言限定符,否则答案始终为“否”。)
- 若有,请继续执行第 4 步。
-
淘汰不含此限定符的资源目录。在该示例中,系统会淘汰所有不含语言限定符的目录。
drawable/ 淘汰
drawable-en/
drawable-en-port/
drawable-en-notouch-12key/
drawable-port-ldpi/ 淘汰
drawable-port-notouch-12key/ 淘汰
例外:如果涉及的限定符是屏幕像素密度,则 Android 会选择最接近设备屏幕密度的选项。通常,Android 倾向于缩小大型原始图像,而不是放大小型原始图像。
- 返回并重复第 2 步、第 3 步和第 4 步,直到只剩下一个目录为止。在此示例中,屏幕方向是下一个判断是否匹配的限定符。因此,未指定屏幕方向的资源被淘汰:
drawable-en/
drawable-en-port/
drawable-en-notouch-12key/
剩下的目录是 drawable-en-port
。
匹配资源的优化
尽管对所请求的每个资源均执行此程序,但是系统仍会对某些方面做进一步优化。 例如,系统一旦知道设备配置,即会淘汰可能永远无法匹配的备用·资源。 比如说,如果配置语言是英语(“en”),则系统绝不会将语言限定符设置为非英语的任何资源目录包含在选中的资源池中(不过,仍会将不带语言限定符的资源目录包含在该池中)。
根据屏幕尺寸(small, large等(已被淘汰))限定符选择资源时,如果没有更好的匹配资源,则系统将使用专为小于当前屏幕的屏幕而设计的资源(例如,如有必要,大尺寸屏幕将使用标准尺寸的屏幕资源)。 但是,如果唯一可用的资源大于当前屏幕,则系统不会使用这些资源,并且如果没有其他资源与设备配置匹配,应用将会崩溃(例如,如果所有布局资源均用 xlarge 限定符标记,但设备是标准尺寸的屏幕)。
所以不建议使用屏幕尺寸,更多使用dpi。
注:限定符的优先顺序 比与设备完全匹配的限定符数量更加重要。例如,在上面的第 4 步中,列表剩下的最后选项包括三个与设备完全匹配的限定符(方向、触摸屏类型和输入法),而 drawable-en 只有一个匹配参数(语言)。但是,语言的优先顺序高于其他两个限定符,因此 drawable-port-notouch-12key 被淘汰。
限定符命名规则:
-
可以为单组资源指定多个限定符,使用短划线分隔
例如:
drawable-en-rUS-land
表示适用于横排美国英语设备 -
限定符必须遵循上面列出的优先级顺序...
若限定符不符合优先级顺序,编译查找资源的时候会报错(
invalid resource directory name
) -
不能嵌套备用资源目录
不能有
res/drawable/drawable-en/
-
名字不区分大小写
编译时编译器会把目录名称转化为小写, 以避免不区分大小写的文件系统出现问题。
-
对于每种限定符类型,仅支持一个值
例如对同一个语言不可能会出现
drawable-rES-rFR
, 而是两个目录drawable-rES
,drawable-rFR
.
对常用限定符举例说明:
drawable-xxhdpi
, mipmap-xxhdpi
, values-fr
, values-zh-rCN
drawable 与mipmap的区别
引入mipmap的原因:在apk应用于手机时,系统会去选择对应的资源目录,有时启动图标ic_launcher
会不合适,但是其他的资源目录已经被过滤掉了,这样导致了在手机显示上,启动图标不正确的现象。而mipmap
可以保留着一个ic_launcher
,而且也仅仅需要一个分辨率的icon,自动会缩放成其他分辨率的ic_launcher
将所有启动器图标放在 res/mipmap-[density]/
文件夹中,而非 res/drawable-[density]/
文件夹中。无论安装应用的设备屏幕分辨率如何,Android 系统都会将资源保留在这些密度特定的文件夹中,例如 mipmap-xxxhdpi
。此 行为可让启动器应用为您的应用选择要显示在主 屏幕上的最佳分辨率图标。
同时,
mipmap
建议只存放应用启动图标,其他的仍放在drawable下。
定位的区别
-
drawbale
For bitmap files (PNG, JPEG, or GIF), 9-Patch image files, and XML files .
资源类型:位图文件(
.png
,.9.png
,jpg
,.gif
)或编译为以下可绘制对象资源子类型的XML文件- 位图文件
- 九宫格(可调整大小的位图),点9图
- 状态列表
- 形状
- 动画可绘制对象
- 其他科绘制对象
-
mipmap
For app launcher icons.
适用于不同启动器图标密度的可绘制对象文件。
icon放置在mipmap文件夹还可以让程序的launcher图标自动拥有跨设备密度展示的能力,例如,一台屏幕密度是xxhdpi的设备可以自动加载mipmap-xxxhdpi下的icon来作为应用程序的launcher图标,这样图标看上去就会更加细腻。
总结---重要!!!
要使应用支持多种设备配置,务必要为使用的每种资源类型提供默认资源,这一点十分十分的重要。
把多个分辨率的
ic_launcher
-启动图标放入mipmap
下,把其他的图片资源放进drawable-xxhdpi
。
- 给资源目录命名时要多注意,是否符合规则, 是否会因为缺少默认资源而导致程序在某些情况下发生
crash
。
参考链接
android developer 支持多种屏幕
android developer 提供资源
android developer android 匹配资源规则
android developer 可绘制对象资源
android developer blog 关于mipmap的建议