提供资源
您应该始终从代码中外部化应用程序资源(如图像和字符串),以便您可以独立维护它们。您还应该为特定设备配置提供备用资源,方法是将它们分组到特殊命名的资源目录中。在运行时,Android使用基于当前配置的适当资源。例如,您可能希望根据屏幕大小或不同的字符串提供不同的UI布局,具体取决于语言设置。
外部化应用程序资源后,可以使用项目R类中生成的资源ID访问它们。访问资源中讨论了如何在应用程序中使用资源。本文档介绍如何在Android项目中对资源进行分组,并为特定设备配置提供备用资源。
分组资源类型
您应该将每种类型的资源放在项目的res /目录的特定子目录中。例如,这是一个简单项目的文件层次结构:
MyProject/
src/
MyActivity.java
res/
drawable/
graphic.png
layout/
main.xml
info.xml
mipmap/
icon.png
values/
strings.xml
正如您在此示例中所看到的,res /目录包含所有资源(在子目录中):图像资源,两个布局资源,启动器图标的mipmap /目录和字符串资源文件。资源目录名称很重要,如表1所示。
注意:有关使用mipmap文件夹的详细信息,请参阅管理项目概述。
表1.项目res /目录中支持的资源目录。
目录 | 资源类型 |
animator/ | 定义属性动画的XML文件。 |
anim/ | 定义补间动画的XML文件。 (属性动画也可以保存在此目录中,但animator /目录是属性动画的首选,以区分这两种类型。) |
color/ | 定义颜色状态列表的XML文件。请参见颜色状态列表资源 |
drawable/ | 位图文件(.png,.9.png,.jpg,.gif)或编译为以下可绘制资源子类型的XML文件:
请参阅Drawable Resources。 |
mipmap/ | 用于不同启动器图标密度的可绘制文件。有关使用mipmap /文件夹管理启动器图标的详细信息,请参阅管理项目概述。 |
layout/ | 定义用户界面布局的XML文件。请参阅布局资源。 |
menu/ | 定义应用程序菜单的XML文件,例如“选项菜单”,“上下文菜单”或“子菜单”。请参阅菜单资源。 |
raw/ | 任意文件以原始形式保存。要使用原始InputStream打开这些资源,请使用资源ID(R.raw.filename)调用Resources.openRawResource()。 但是,如果需要访问原始文件名和文件层次结构,可以考虑在assets /目录中保存一些资源(而不是res / raw /)。资产/中的文件未获得资源ID,因此您只能使用AssetManager读取它们。 |
values/ | 包含简单值的XML文件,例如字符串,整数和颜色。 其他res /子目录中的XML资源文件基于XML文件名定义单个资源,而values /目录中的文件描述多个资源。对于此目录中的文件,<resources>元素的每个子元素都定义一个资源。例如,<string>元素创建一个R.string资源,<color>元素创建一个R.color资源。 由于每个资源都使用自己的XML元素定义,因此您可以根据需要为文件命名,并将不同的资源类型放在一个文件中。但是,为清楚起见,您可能希望将不同的资源类型放在不同的文件中。例如,以下是您可以在此目录中创建的资源的一些文件名约定:
|
xml/ | 可以通过调用Resources.getXML()在运行时读取的任意XML文件。必须在此处保存各种XML配置文件,例如可搜索的配置。 |
警告:永远不要将资源文件直接保存在res /目录中 - 这将导致编译器错误。
有关某些类型资源的更多信息,请参阅“资源类型”文档。
您在表1中定义的子目录中保存的资源是您的“默认”资源。也就是说,这些资源定义了应用程序的默认设计和内容。但是,不同类型的Android驱动设备可能需要不同类型的资源。例如,如果设备的屏幕大于普通屏幕,则应提供不同的布局资源,以利用额外的屏幕空间。或者,如果设备具有不同的语言设置,则应提供不同的字符串资源来翻译用户界面中的文本。要为不同的设备配置提供这些不同的资源,除了默认资源之外,还需要提供备用资源。
提供替代资源
几乎每个应用程序都应提供替代资源来支持特定的设备配置。例如,您应该为不同的屏幕密度和不同语言的替代字符串资源包含替代的可绘制资源。在运行时,Android会检测当前设备配置并为您的应用程序加载适当的资源。
要为一组资源指定特定于配置的备选方案:
1.在res / named中以<resources_name> - <config_qualifier>的形式创建一个新目录。
- <resources_name>是相应默认资源的目录名称(在表1中定义)。
- <qualifier>是一个名称,它指定要使用这些资源的单个配置(在表2中定义)。
您可以附加多个<qualifier>。用破折号分开每一个。
警告:附加多个限定符时,必须将它们放在表2中列出的顺序中。如果排序错误,则忽略资源。
2.将相应的备用资源保存在此新目录中。资源文件的名称必须与默认资源文件完全相同。
例如,以下是一些默认和替代资源:
res/
drawable/
icon.png
background.png
drawable-hdpi/
icon.png
background.png
hdpi限定符表示该目录中的资源适用于具有高密度屏幕的设备。这些可绘制目录中的图像的大小适合特定的屏幕密度,但文件名完全相同。这样,用于引用icon.png或background.png图像的资源ID始终相同,但Android通过将设备配置信息与中的限定符进行比较来选择与当前设备最匹配的每种资源的版本。资源目录名称。
Android支持多个配置限定符,您可以通过将每个限定符与短划线分隔,将多个限定符添加到一个目录名称。表2按优先顺序列出了有效的配置限定符 - 如果对资源目录使用多个限定符,则必须按照表中列出的顺序将它们添加到目录名中。
表2.配置限定符名称。
配置 | 限定符值 | 说明 |
MCC和MNC | 例子: mcc310 mcc310-mnc004 mcc208-mnc00 等等 | 移动国家/地区代码(MCC),可选地后跟设备中SIM卡的移动网络代码(MNC)。例如,mcc310在任何运营商上都是美国,mcc310-mnc004在Verizon是美国,而mcc208-mnc00在Orange上是法国。 如果设备使用无线电连接(GSM电话),则MCC和MNC值来自SIM卡。
您也可以单独使用MCC(例如,在您的应用程序中包含特定国家/地区的法律资源)。如果您只需要根据语言指定,那么请改用语言和区域限定符(下面讨论)。如果您决定使用MCC和MNC限定符,则应谨慎操作并测试其是否按预期工作。
另请参阅配置字段mcc和mnc,它们分别表示当前的移动国家代码和移动网络代码。 |
语言和地区 | 例子:en fr en-rUS fr-rFR fr-rCA 等等 | 该语言由两个字母的ISO 639-1语言代码定义,可选地后跟两个字母的ISO 3166-1-alpha-2区域代码(以小写“r”开头)。
|
布局方向 | ldrtl ldltr | 应用程序的布局方向。 ldrtl的意思是“布局方向 - 从右到左”。 ldltr表示“layout-direction-left-right”,是默认的隐式值。
在API级别17中添加。 |
最小宽度 | SW <N> DP 例子: sw320dp sw600dp sw720dp 等等 | 屏幕的基本尺寸,由可用屏幕区域的最短尺寸表示。具体来说,设备的最小宽度是屏幕可用高度和宽度的最短值(您也可以将其视为屏幕的“最小可能宽度”)。您可以使用此限定符来确保无论屏幕的当前方向如何,您的应用程序的UI宽度至少为<N> dps。
当您的应用程序为smallestWidth限定符提供不同值的多个资源目录时,系统使用最接近(不超过)设备的smallestWidth的值。 |
可用宽度 | w<N> DP 例子: w720dp w1024dp 等等 | 指定最小可用屏幕宽度,以dp为单位,应使用资源 - 由<N>值定义。当方向在横向和纵向之间变化以匹配当前实际宽度时,此配置值将更改。 当您的应用程序为此配置提供具有不同值的多个资源目录时,系统将使用最接近(不超过)设备当前屏幕宽度的值。这里的值考虑了屏幕装饰,因此如果设备在显示器的左边缘或右边缘具有一些持久性UI元素,则它使用小于实际屏幕大小的宽度值,考虑这些UI元素和减少应用程序的可用空间。 在API级别13中添加。 另请参阅screenWidthDp配置字段,该字段包含当前屏幕宽度。 |
可用高度 | ħ<N> DP 例子: h720dp h1024dp 等等 | 指定最小可用屏幕高度,以“dp”为单位,应使用资源 - 由<N>值定义。当方向在横向和纵向之间变化以匹配当前实际高度时,此配置值将更改。
|
屏幕尺寸 | small normal large xlarge | small:屏幕尺寸与低密度QVGA屏幕相似。小屏幕的最小布局尺寸约为320x426 dp单位。例子是QVGA低密度和VGA高密度。
在API级别4中添加。 |
屏幕方面 | long notlong | 长:长屏幕,如WQVGA,WVGA,FWVGA notlong:不长的屏幕,如QVGA,HVGA和VGA 在API级别4中添加。 这完全基于屏幕的宽高比(“长”屏幕更宽)。这与屏幕方向无关。 另请参阅screenLayout配置字段,该字段指示屏幕是否很长。 |
圆形屏幕 | round notround | round :圆形屏幕,例如圆形可穿戴设备notround:矩形屏幕,如手机或平板电脑 在API级别23中添加。 另请参阅isScreenRound()配置方法,该方法指示屏幕是否为圆形。 |
屏幕方向 | port land | port :设备处于纵向(垂直)land:设备处于横向(水平) 如果用户旋转屏幕,这可能会在应用程序的生命周期内发生变化。有关在运行时如何影响应用程序的信息,请参阅处理运行时更改。 另请参阅方向配置字段,该字段指示当前设备方向。 |
UI模式 | car desk television | 汽车:设备显示在汽车码头 手表:设备有一个显示器,戴在手腕上 |
夜间模式 | night notnight | night :晚上notnight:白天 在API级别8中添加。 如果夜间模式处于自动模式(默认),则在应用程序的生命周期内可能会发生变化,在这种情况下,模式会根据一天中的时间而变化。您可以使用UiModeManager启用或禁用此模式。有关在运行时如何影响应用程序的信息,请参阅处理运行时更改。 |
屏幕像素密度(dpi) | ldpi mdpi hdpi xhdpi xxhdpi xxxhdpi nodpi tvdpi anydpi | ldpi:低密度屏幕;大约120dpi。
有关如何处理不同屏幕密度以及Android如何扩展位图以适应当前密度的详细信息,请参阅支持多个屏幕。 |
触摸屏类型 | notouch finger | notouch:设备没有触摸屏。 finger:设备有一个触摸屏,旨在通过用户手指的方向交互来使用。 另请参阅触摸屏配置字段,该字段指示设备上触摸屏的类型。 |
键盘可用性 | keysexposed keyshidden keyssoft | keysexposed:设备有键盘可用。如果设备启用了软件键盘(很可能),即使硬件键盘没有暴露给用户,即使设备没有硬件键盘,也可以使用此键盘。如果未提供软件键盘或已禁用软键盘,则仅在暴露硬件键盘时使用。 keyshidden:设备有一个可用的硬件键盘,但它是隐藏的,并且设备没有启用软件键盘。 keyssoft:设备启用了软件键盘,无论是否可见。 如果您提供keysexposed资源,但不提供keyssoft资源,只要系统启用了软件键盘,系统就会使用密钥接收资源,而不管键盘是否可见。 如果用户打开硬件键盘,这可能会在应用程序的生命周期内发生变化。有关在运行时如何影响应用程序的信息,请参阅处理运行时更改。 另请参阅配置字段hardKeyboardHidden和keyboardHidden,它们分别指示硬件键盘的可见性以及任何类型键盘(包括软件)的可见性。 |
主要文本输入法 | nokeys qwerty 12key | nokeys:设备没有用于文本输入的硬件键。 qwerty:设备具有硬件qwerty键盘,无论用户是否可见。 12键:设备有一个硬件12键键盘,无论用户是否可见。 另请参阅键盘配置字段,该字段指示可用的主要文本输入方法。 |
导航按钮可用性 | navexposed navhidden | navexposed:导航键可供用户使用。 navhidden:导航键不可用(例如在关闭的盖子后面)。 如果用户显示导航键,则可以在应用程序的生命周期内更改。有关在运行时如何影响应用程序的信息,请参阅处理运行时更改。 另请参阅navigationHidden配置字段,该字段指示是否隐藏导航键。 |
主要的非触摸式导航方法 | nonav dpad trackball wheel | nonav:设备除了使用触摸屏之外没有导航设施。 dpad:设备有一个方向键(d-pad)用于导航。 轨迹球:设备有轨迹球用于导航。 wheel:设备有一个导航方向盘(不常见)。 另请参阅导航配置字段,该字段指示可用的导航方法的类型。 |
平台版本(API级别) | v3 v4 v7 | 设备支持的API级别。例如,API级别1的v1(Android 1.0或更高版本的设备)和API级别4的v4(Android 1.6或更高版本的设备)。有关这些值的详细信息,请参阅Android API级别文档。 |
注意:自Android 1.0以来添加了一些配置限定符,因此并非所有版本的Android都支持所有限定符。使用新的限定符会隐式添加平台版本限定符,以便旧设备肯定会忽略它。例如,使用w600dp限定符将自动包含v13限定符,因为可用宽度限定符在API级别13中是新的。为避免任何问题,请始终包含一组默认资源(一组没有限定符的资源)。有关更多信息,请参阅有关提供与资源的最佳设备兼容性的部分。
限定符名称规则
以下是有关使用配置限定符名称的一些规则:
- 您可以为一组资源指定多个限定符,用短划线分隔。例如,drawable-en-rUS-land适用于横向美国英语设备。
- 限定符必须按表2中列出的顺序排列。例如:
Wrong: drawable-hdpi-port/
Correct: drawable-port-hdpi/
- 备用资源目录不能嵌套。例如,你不能有res / drawable / drawable-en /。
- 值不区分大小写。资源编译器在处理之前将目录名称转换为小写,以避免在不区分大小写的文件系统上出现问题。名称中的任何大写都只是为了提高可读性。
- 每种限定符类型只支持一个值。例如,如果要为西班牙和法国使用相同的可绘制文件,则不能有名为drawable-rES-rFR /的目录。相反,您需要两个资源目录,例如drawable-rES /和drawable-rFR /,它们包含相应的文件。但是,您无需在两个位置实际复制相同的文件。相反,您可以为资源创建别名。请参阅下面的创建别名资源。
将备用资源保存到使用这些限定符命名的目录后,Android会根据当前设备配置自动应用应用程序中的资源。每次请求资源时,Android都会检查包含所请求资源文件的备用资源目录,然后找到最匹配的资源(如下所述)。如果没有与特定设备配置匹配的备用资源,则Android使用相应的默认资源(不包含配置限定符的特定资源类型的资源集)。
创建别名资源
当您拥有要用于多个设备配置的资源(但不希望提供作为默认资源)时,您不需要将同一资源放在多个备用资源目录中。相反,您可以(在某些情况下)创建备用资源,该资源充当保存在默认资源目录中的资源的别名。
注意:并非所有资源都提供了一种机制,您可以通过该机制为其他资源创建别名。特别是,xml /目录中的动画,菜单,原始和其他未指定的资源不提供此功能。
例如,假设您有一个应用程序图标,icon.png,并且需要针对不同区域设置的唯一版本。但是,两个语言环境,英语 - 加拿大语和法语 - 加拿大语,需要使用相同的版本。您可能认为需要将相同的图像复制到英语 - 加拿大语和法语 - 加拿大语的资源目录中,但事实并非如此。相反,您可以将用于两者的图像保存为icon_ca.png(除icon.png以外的任何名称)并将其放在默认的res / drawable /目录中。然后在res / drawable-en-rCA /和res / drawable-fr-rCA /中创建一个icon.xml文件,该文件使用<bitmap>元素引用icon_ca.png资源。这允许您只存储一个版本的PNG文件和两个指向它的小XML文件。 (示例XML文件如下所示。)
Drawable
要为现有drawable创建别名,请使用<bitmap>元素。例如:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/icon_ca" />
如果将此文件另存为icon.xml(在备用资源目录中,例如res / drawable-en-rCA /),则会将其编译为可以引用为R.drawable.icon的资源,但实际上是别名对于R.drawable.icon_ca资源(保存在res / drawable /中)。
Layout
要为现有布局创建别名,请使用包含在<merge>中的<include>元素。例如:
<?xml version="1.0" encoding="utf-8"?>
<merge>
<include layout="@layout/main_ltr"/>
</merge>
如果将此文件另存为main.xml,则会将其编译为可引用为R.layout.main的资源,但实际上是R.layout.main_ltr资源的别名。
字符串和其他简单的值
要为现有字符串创建别名,只需使用所需字符串的资源ID作为新字符串的值。例如:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello</string>
<string name="hi">@string/hello</string>
</resources>
R.string.hi资源现在是R.string.hello的别名。
其他简单的值以相同的方式工作。例如,颜色:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="red">#f00</color>
<color name="highlight">@color/red</color>
</resources>
提供与资源的最佳设备兼容性
为了使您的应用程序支持多种设备配置,始终为应用程序使用的每种资源类型提供默认资源非常重要。
例如,如果您的应用程序支持多种语言,则始终包含值/目录(在其中保存字符串),而不包含语言和区域限定符。如果您将所有字符串文件放在具有语言和区域限定符的目录中,那么在设置为字符串不支持的语言的设备上运行时,应用程序将崩溃。但是,只要您提供默认值/资源,那么您的应用程序将正常运行(即使用户不理解该语言 - 它比崩溃更好)。
同样,如果您根据屏幕方向提供不同的布局资源,则应选择一个方向作为默认方向。例如,不是在layout-land / for landscape和layout-port / for portrait中提供布局资源,而是将其中一个保留为默认值,例如layout / for landscape和layout-port / for portrait。
提供默认资源非常重要,不仅因为您的应用程序可能在您未预料到的配置上运行,而且因为Android的新版本有时会添加旧版本不支持的配置限定符。如果您使用新的资源限定符,但保持与旧版Android的代码兼容性,那么当旧版本的Android运行您的应用程序时,如果您不提供默认资源,它将会崩溃,因为它无法使用以新命名的资源预选赛。例如,如果您的minSdkVersion设置为4,并且您使用夜间模式(夜晚或非夜晚,在API级别8中添加)限定了所有可绘制资源,则API级别4设备无法访问您的可绘制资源并将崩溃。在这种情况下,您可能希望notnight成为默认资源,因此您应该排除该限定符,以便您的可绘制资源处于drawable /或drawable-night /。
因此,为了提供最佳的设备兼容性,请始终为应用程序正常执行的资源提供默认资源。然后使用配置限定符为特定设备配置创建备用资源。
此规则有一个例外:如果应用程序的minSdkVersion为4或更高,则在使用屏幕密度限定符提供备用可绘制资源时,不需要默认的可绘制资源。即使没有默认的可绘制资源,Android也可以在替代屏幕密度中找到最佳匹配,并根据需要缩放位图。但是,为了获得所有类型设备的最佳体验,您应该为所有三种类型的密度提供替代的绘图。
Android如何找到最匹配的资源
当您请求为其提供备选方案的资源时,Android会根据当前设备配置选择在运行时使用哪个备用资源。为了演示Android如何选择替代资源,假设以下可绘制目录各自包含相同图像的不同版本:
drawable/ drawable-en/ drawable-fr-rCA/ drawable-en-port/ drawable-en-notouch-12key/ drawable-port-ldpi/ drawable-port-notouch-12key/
并假设以下是设备配置:
Locale = en-GB
Screen orientation = port
Screen pixel density = hdpi
Touchscreen type = notouch
Primary text input method = 12key
通过将设备配置与可用的替代资源进行比较,Android从drawable-en-port中选择drawable。
系统根据以下逻辑决定使用哪些资源:
1.消除与设备配置相矛盾的资源文件。
drawable-fr-rCA /目录被删除,因为它与en-GB语言环境相矛盾。
drawable/ drawable-en/drawable-fr-rCA/drawable-en-port/ drawable-en-notouch-12key/ drawable-port-ldpi/ drawable-port-notouch-12key/
例外:屏幕像素密度是由于矛盾而未消除的一个限定符。即使设备的屏幕密度是hdpi,也不会消除drawable-port-ldpi /,因为此时每个屏幕密度都被认为是匹配的。有关详细信息,请参阅“支持多个屏幕”文档。
2.选择列表中的(下一个)最高优先级限定符(表2)。 (从MCC开始,然后向下移动。)
3.任何资源目录都包含此限定符吗?
- 如果否,返回步骤2并查看下一个限定符。 (在示例中,答案是“否”,直到达到语言限定符。)
- 如果是,请继续执行步骤4。
4.消除不包含此限定符的资源目录。在该示例中,系统将删除所有不包含语言限定符的目录:
drawable/drawable-en/ drawable-en-port/ drawable-en-notouch-12key/drawable-port-ldpi/drawable-port-notouch-12key/
例外:如果有问题的限定符是屏幕像素密度,Android会选择与设备屏幕密度最匹配的选项。通常,Android倾向于缩小较大的原始图像以放大较小的原始图像。请参阅支持多个屏幕。
5.返回并重复步骤2,3和4,直到只剩下一个目录。在示例中,屏幕方向是下一个有任何匹配的限定符。因此,消除了未指定屏幕方向的资源:
drawable-en/drawable-en-port/drawable-en-notouch-12key/
剩下的目录是drawable-en-port。
虽然针对所请求的每个资源执行该过程,但系统进一步优化了一些方面。一种这样的优化是,一旦设备配置已知,它可能会消除永远不能匹配的替代资源。例如,如果配置语言是英语(“en”),那么将语言限定符设置为英语以外的任何资源目录永远不会包含在已检查的资源池中(尽管没有语言限定符的资源目录仍然是包括在内)。
当根据屏幕大小限定符选择资源时,如果没有更好匹配的资源,系统将使用为小于当前屏幕的屏幕设计的资源(例如,如果需要,大尺寸屏幕将使用正常大小的屏幕资源)。但是,如果唯一可用的资源大于当前屏幕,则系统将不使用它们,如果没有其他资源与设备配置匹配,则应用程序将崩溃(例如,如果所有布局资源都使用xlarge限定符标记,但是设备是正常大小的屏幕)。
注意:限定符的优先级(在表2中)比与设备完全匹配的限定符的数量更重要。例如,在上面的步骤4中,列表中的最后一个选项包括与设备完全匹配的三个限定符(方向,触摸屏类型和输入方法),而drawable-en只有一个匹配(语言)的参数。但是,语言的优先级高于其他限定符,因此drawable-port-notouch-12key已经完成。
要了解有关如何在应用程序中使用资源的更多信息,请继续参阅“访问资源”。