资源:
代码中使用到的文件,静态文本。包括位图,布局文件,字符串,动画等等。
开发中,要外部化资源,如图像和字符串,有利于维护资源。同时必要时也可以为不同设备提供支持。
一、资源分组
1.默认资源:
MyProject/
src/
MyActivity.java
res/
drawable/
graphic.png
layout/
mipmap/
values/
strings.xml
res下放的就是资源文件,不同的文件夹则代表不同的资源分组。下面将一一介绍:
animator/:属性动画XML;
anim/:view动画(平移、旋转、缩放、透明度)XML;属性动画也可放在这里,但是为了好区分分开。
color/:颜色状态列表;
drawable/:位图文件(.png、.9.png、.jpg、.gif)或可绘制对象资源类型的XML:位图、九宫格、状态列表、形状、动画可绘制对象、其他可绘制对象。
mipmap/:用于不同启动器图标密度的可绘制对象文件。注意,很多人认为将drawable中的文件资源放在这里,其实这里只适用于启动器图标。
layout/:用户界面布局;
menu/:菜单(选项菜单、上下文菜单或子菜单);
raw/:原始形式保存的文件。要使用InputStream打开,用资源ID(R.raw.filename)调用Resources.openRawResource();但如需通过路径和文件名访问,则将资源保存在assets/目录,该目录中没有资源ID,只能使用AssetManager读取。
values/:字符串、颜色等值的XML,其中每个文件可以包含多个资源。arrays.xml:数组资源(类型化数组,可以使string、int、bitmap等等,通过TypedArray的get...()获取);colors.xml:颜色值;dimens.xml:尺寸值;strings.xml:字符串值;styles.xml:样式。
xml/:使用Resources.getXML()读取任意XML文件。各种XML配置文件都必须保存在这。
注意:不要将资源文件直接保存在res/目录内,会导致变异错误。
以上为默认资源,此外,还有备用资源,用以支持不同的设备、尺寸、语言等。具体的资源类型定义及使用,请参考官方文档中guide中的资源类型。
2.备用资源:
根据不同设备配置来选择使用不同的资源。
采用限定符指定适用的配置。<resources_name>-<config_qualifier>,可包含多个限定符,用-分隔,但要按照下面介绍的顺序,否则资源将被忽略。同时资源文件名称必须与默认资源文件一致。
常用限定符:
语言和区域:en,fr,en-rUs,zh-rCN等,不区分大小写,r用于区分区域码。不能单独制定区域。
布局方向(api17):ldrtl,布局方向从右到左(阿拉伯语等会这样布局);ldltr,布局方向从左到右,是默认的隐式值。
最小尺寸(api13):sw<N>dp,如sw600dp等,只可用屏幕尺寸最小宽度要有600dp,低于这个值则无法使用。smallestWidth是设备固定屏幕尺寸特性,不会随屏幕旋转而变化。
可用宽度(api13):w<N>dp,如w720dp,最小可用屏幕宽度。横纵向切换会发生变化。当有多个配置都满足时,如,w720dp和w1024dp,都满足,则会优先选择最接近设备属性的那个。
可用高度(api13):h<N>dp,如h720dp,与上述宽度一样,只是用于高度。
屏幕尺寸:samll,低密度,最小布局尺寸为320*426dp;normal,中等密度,标准屏幕最小布局尺寸约为320*470dp;large,中等密度,大屏幕最小布局尺寸为480*640dp;xlarge,大于中等密度,最小布局尺寸为720*960dp。该配置并不仅适用于指定设备,如果没有匹配的资源,会选择与之最近的。如果所有资源均大于当前屏幕的尺寸限定符,则系统不会使用这些资源,且应用运行时会崩溃。
屏幕方向:prot,纵向;land,横向。
屏幕像素密度:ldpi,低密度,约120dpi;mdpi,中等密度,160dpi;hdpi,高密度,240dpi;xhdpi,超高密度,320dpi;xxhdpi,超超高密度,480dpi;xxxhdpi,超超超高密度,640dpi;nodpi,不希望以匹配设备密度的位图资源;tvdpi,主要用于电视,约213dpi。anydpi,适用于所有密度,优先级高于其他限定符。对矢量可绘制对象有用。l:m:h:xh:xxh:xxxh为1.5:2:3:4:6:8,可用于位图的尺寸比例,如ldpi为9*9,则m为12*12,以此类推。同样的,该配置并不仅适用于指定设备,如果没有匹配的资源,会选择与之最相近的。
平台版本:v4(API4),v7(API7)等。
注:上述只是部分,更多请参考官方文档。并非所有版本都支持所有限定符。例如,使用w600dp,会自动包括v13限定符等等。
限定符命名规则:
1)可以为单组资源指定多个限定符,并用短线分隔;
2)多限定符必须按照上面列出的顺序命名;
3)不能嵌套备用资源。如,不能res/drawable/drawable-en/;
4)不区分大小写;
5)每种限定符,只支持一个值。
3.别名资源
如果想将资源用于多种设备(不作为默认资源),无需将资源放入多个目录,可创建备用资源,充当保存在默认资源目录下的资源别名。但并不是所有资源都有别名机制。
例如,一个图标icon.png,有两种语言使用该图标,则不需要将其复制到两种语言对应的文件夹,只需要将其另存除出icon.png之外的其他名字,如icon_ca.png,并放入默认目录res/目录中,在对应语言文件夹中创建icon.xml,使用<bitmap>元素引用icon_ca.png资源,这样可以只存储png文件的一个版本,和两个指向该版本的小型文件。
可绘制对象:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/icon_ca" />
布局:
<?xml version="1.0" encoding="utf-8"?>
<merge>
<include layout="@layout/main_ltr"/>
</merge>
字符串和其他简单值:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello</string>
<string name="hi">@string/hello</string>
</resources>
其他简单值:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="red">#f00</color>
<color name="highlight">@color/red</color>
</resources>
二、利用资源提供最佳设备兼容
注意,一定要提供默认资源。因为如果没有默认资源,在一些匹配不了给定配置资源的机器上,就会crash。例如,语言一定要有默认的values目录。屏幕方向一般建议只指定一个方向layout-port/或layout-land目录即可,默认的则为另一个方向。并且,有些新版本会添加限定符,在老版本上无法解析,如果不提供默认资源,就会crash。其中有个例外,就是在minSdkVersion为4或更高版本,提供带屏幕限定符的备用可绘制对象资源时,不需要默认可绘制对象资源。即使没有默认资源,系统也会从备用资源中找到最合适的资源。请参考我的另一篇博客,多屏幕最佳实践。
三、Android查找最佳匹配资源规则
当请求资源时,Android会根据设备配置选择要在运行时使用的备用资源。系统将以以下的逻辑决定要使用的资源:
1.淘汰与设备配置冲突的资源文件。(屏幕像素密度是唯一的例外,它会匹配所有相关文件夹的最佳匹配项);
2.选择限定符列表中优先级最高的限定符;
3.判断是否有资源目录包括此限定符?无,返回第2步,查看下一个限定符;有则进行下一步;
4.淘汰不含此限定符的资源目录。(屏幕像素密度除外,Android会选择最接近设备密度的选项,且一般会倾向于缩小大图,而不是放大小图);
5.返回并重复第2、3、4步,直到只剩下一个目录为止。
系统会对上面的一些步骤进行优化。比如,当语言是中文时,其会淘汰配置不是默认资源和中文的选项。
在匹配屏幕尺寸时,如果没有匹配到,则会使用小于当前屏幕设计的资源。但是如果唯一可用的资源大于当前屏幕,系统将不会使用这些资源,将会崩溃。