一直以来对于系统选择资源文件的流程都模糊不清,每次定义资源的时候都战战兢兢,终于忍无可忍,无需再忍,决定掏出官方文档来仔细瞧一瞧。摘要记录,以防忘记。
资源类型
一个简单的项目目录如下所示:
其中资源文件放置在res目录下,res支持的资源目录和类型如下:
目录 | 资源类型 |
---|---|
animator/ | 定义属性动画的XML文件 |
anim/ | 定义渐变动画的XML文件 |
color/ | 定义颜色状态表的XML文件 |
drawable/ | 位图文件(.png、.9.png、.jpg、.gif)或者可编译为以下类型的XML文件:位图文件、九宫格文件、状态列表文件(State List)、形状(Shape)、动画可绘制文件(Animation drawables)等等 |
mipmap/ | 不同密度的Launcher图标文件 |
layout/ | 布局XML文件 |
menu/ | 菜单XML文件 |
raw/ | 原始资源文件,使用资源id进行访问,如需要文件名进行访问,可放置到assets/目录下 |
values/ | 字符串、整型和样式等简单值的XML文件,该目录文件夹下可以有子目录,每个文件都以标签<resources>定义资源,本可以将所有的简单资源文件定义到一个XML文件中,但为了结构的清晰,我们一般使用arrays.xml来定义资源数组,colors.xml来定义颜色值,dimens.xml定义尺寸值,strings.xml来定义字符串值,styles.xml来定义样式 |
xml/ | 运行时可通过Resources.getXML()读取的XML文件 |
资源选择
资源命名
对于一个资源文件,针对设备的不同,需要提供一整套的资源文件供程序运行时根据设备和运行条件(横屏或者竖屏、移动还是联通)的不同来选择合适的资源文件。
资源文件必须名称相同地放置到合适的资源文件夹下面,而资源文件夹的命名至关重要。资源文件夹必须严格按照“资源类型名称-配置1-配置2-...”的方式进行命名,如图2中,drawable是资源类型,hdpi是一个分辨率的配置。在drawable-hdpi和drawble文件夹中分别放置相同名称的高分辨率和默认配置的2个资源文件。
设备在运行时选择资源的标准就是按照资源文件夹的命名来匹配选择最优的资源文件。 设备按如下表的配置顺序依次匹配来选择最佳的资源(注意:下表的配置仅为主要配置,不是全部。):
配置 | 限定符值 | 说明 |
---|---|---|
MCC MNC | 示例:mcc460 中国 mcc460-mnc00 中国移动 | mcc移动国家代码,mnc 移动网络代码,mcc460是中国任一运营商,mcc460-mnc00 中国移动 |
语言和区域 | 示例:zh_rCN,zh_rTW,zh_rHK | zh,中文语言缩写,r后面跟区域码,CN大陆,TW台湾,HK香港,这个用户在使用过程中是有可能改变的 |
布局方向 | ldrtl,ldltr | 布局由右向左ldrtl,由左向右ltr |
smallestWidth | sw<N>dp,示例sw320dp,sw600dp | 屏幕高度和宽度的最小尺寸,一个sw320dp的文件夹定义的资源只有在高度和宽度都大于320dp的情况下才可能被使用。 |
可用宽度 | w<N>dp,示例w720dp,w960dp | 当可用宽度大于指定宽度时,即可能被选中,宽度在横向和纵向切换时是可变的。例如一个1024*720dp的设备在纵向时不可能匹配w960dp,而在横向时则有可能。在匹配时选择接近但未超出当前屏幕宽度的值。 |
可用高度 | h<N>dp | 跟可用宽度的匹配一样 |
屏幕尺寸 | small,normal,large,xlarge | small指屏幕尺寸小于3英寸,normal小于4.5英寸,large是4.5英寸-7英寸之间,xlarge是7-10英寸之间 链接 |
屏幕纵横比 | long,notlong | long 宽屏 如 WQVGA,,WVGA,FWVGA(带W的),not long 非宽屏,如QVGA,HVGA,VGA |
圆形屏幕 | round,not round | round:圆形屏幕,例如圆形可穿戴设备,not round 方形屏幕,手机和电脑 |
屏幕方向 | port,land | port 纵向,land 横向 |
UI模式 | car,desk,televesion,applicance,watch | car 车载显示;desk 桌面手机显示,television 电视显示,applicance 不带显示屏的,watch 手腕设备 |
夜间模式 | night,notnight | night 夜间,notnight 白天,根据时间进行显示,可以通过UiModeManager启用和关闭 |
屏幕密度(dpi) | ldpi,mdip,hdpi,xhdpi,xxhdpi,xxxhdpi,nodpi,tvdpi,anydpi | ldpi:120dpi,mdpi:160dpi,hdpi:240dpi,xhdpi:320dpi,xxhdpi:480dpi,xxxhdpi:640dpi,按照3:4:6:8:12:16的比例。nodpi,不希望被缩放的位图资源,anydpi 任意密度的屏幕。 |
触摸类型 | nottouch,finger | nottouch:没有触摸屏,finger:手指交互的触摸屏 |
键盘可用性 | keysexposed,keyhidden,keyssoft | keyexposed 硬键盘可用。keyshidden 硬键盘可用,但隐藏了,同时没有启动软键盘。keyssoft 启用软键盘。 |
输入法 | nokeys,qwerty,12key | nokeys:设备没有硬按键,qwerty设备具有标准硬键盘,12ke设备具有12键硬键盘 |
API版本 | v3,v7,v11等等 | 设备的API级别,v1即设备API级别为1或者更高 |
对于资源文件夹的命名必须按照上表中的顺序依次配置,切不可倒置。
- 错误:drawable-hdpi-port/
- 正确:drawable-port-hdpi/
选择资源
android系统按照如图3所示进行资源的匹配选择。
例如app有以下资源文件夹:
drawable/
drawable-en/
drawable-fr-rCA/
drawable-en-port/
drawable-en-notouch-12key/
drawable-port-ldpi/
drawable-port-notouch-12key/
系统配置:
运营商 = mcc400-mnc00
语言区域 = en-rGB
屏幕方向 = port
屏幕密度 = hdpi
触屏类型 = nottouch
开始选择:
- 取出第一个配置:mcc400-mnc00,发现所有的配置中都不包含此种类型的配置,不冲突不包含,跳过该配置
- 取出第二个配置:en-rGB
- 移除与en配置冲突的 drawable-fr-rCA
- 移除那些不包含此配置的资源文件夹 drawable-port-ldpi/ drawable-port-notouch-12key/
- 取出第屏幕方向布局就只剩下资源文件夹drawable-en-port/
设备兼容性
请确保每种配置都有一个默认的资源可以进行选择,这样在出现设备没有任何匹配文件夹的情况下可以选择默认的文件夹中的资源而不至于导致系统崩溃。例如,如果我们只配置2种文件夹values-en,values-zh,那么在设备语言为法语(fr)的情况下,按照先移除冲突的资源文件夹的准则,这2个资源文件夹都被移除了已经没有其他可以选择的资源文件了,系统会崩溃,所有任何资源文件夹都请保留一个默认名称的资源文件夹。
创建别名资源
有时候有些资源希望在不同的配置下可以服用,例如一个很大的背景图片希望在语言为中文(zh)和英文(en)的情况下都使用,这时候如果在drawable-zh和drawable-en的文件夹下面都放置一种图片当然是可以的,只是这样会造成apk的体积过大。这时候可以将此图拷贝到drawable/文件夹下命名为icon_zh_en,而在
drawable-en和drawable-zh文件夹下分别保存下面的icon.xml文件,那么同样载en和zh的配置下也可以通过引用R.drawable.icon引用到图片,从而对apk瘦身。同样对于资源文件、数组、布局文件都可以使用别名来引用以达到避免资源重复的问题。
<!--icon.xml-->
<?xml version="1.0" encoding="utf-8"?>
<resources>
<drawable name="icon">@drawable/icon_zh_en</drawable>
</resources>