黑马程序员android 应用程序资源 以及访问

来源:互联网 发布:妩媚的女生 知乎 编辑:程序博客网 时间:2024/06/10 09:48

 ------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------

你应该经常外部化你应用程序代码中的资源,比如图片、字符串等,这样有利于你独立处理这些资源。你也应该根据特定的设备配置提供一些可替代的资源,并且把他们分组保存在指定的路径名下。运行时,Android可以根据当前的配置使用适当的资源。比如,你也许会根据不同的屏幕尺寸提供不同的UI布局或是不同的语言设定提供不同的字符串。


一旦你外部化了应用程序中的资源,你就能通过项目中的R类<class>生成的ID来调用他们。怎么使用你的资源将在资源访问-Accessing Resources具体讨论。这篇文档将向你展示怎么样分类你Android项目中的资源,以及怎么样给特定的设备配置提供可替代的资源。


分组资源类型-Grouping Resource Types

你应该把每一种类型的资源分别放在你的项目中res/中特定的子路径下。这是一个简单的项目中,文件分层的例子:

MyProject/
src/
MyActivity.java
res/
drawable/
icon.png
layout/
main.xml
info.xml
values/
strings.xml

从这个例子中你可以看到,res/路径下包含了所有类型的资源(在每一个子路径中):一个图片资源,两个布局资源和一个字符串资源文档。资源路径名非常重要,并在表1中做了具体描述。

表1 项目res/下的资源路径
路径资源animator/XML文件,定义了属性动画-property animationsanim/XML文件,定义了渐变动画-tween animations. (属性动画-property animations也能保存在这个路径下, 但animator/路径是专为属性动画-property animations准备的,用来区别这两种类型的动画)color/XML文件,定义了一个颜色状态列表. 详见颜色状态列表资源-Color State List Resourcedrawable/位图(.png, .9.png, .jpg, .gif)或XML文件, 编译成以下绘图资源子类型:
  • 位图文件
  • Nine-Patches (尺寸可变的位图)
  • 状态列表
  • 形状
  • 动画画板
  • 其他绘图
    详见绘图资源-Drawable Resources.
layout/XML文件,定义了用户接口布局. 详见布局资源-Layout Resource.menu/XML文件,定义了应用程序的菜单,如选择菜单<Options Menu>,快捷菜单<Context Menu>和子菜单.详见菜单资源-Menu Resource.raw/任意的原始格式文件。用InputStream来打开这些资源,通过资源ID,调用Resources.openRawResource()方法,即R.raw.filename

但是,如果你想调用原始的文件名和文件层级,你应该考虑把这些资源保存在assets/路径下(而不是res/raw/).在assets/中的文件不会被赋予资源ID,所以你只能通过AssetManager类来读取它们。

values/XML文件,包含了基本数值,如字符串,整型和颜色。

res/路径下的其他XML资源文件中定义了单个基于XML文件名的资源,然而,在values/路径下描述了多个资源。在这个路径下的文件中,每一个子资源<recources>元素都定义了一个单独的资源。比如,一个字符串<string>元素创建了一个R.string资源,一个颜色<color>元素创建了一个R.color资源。

因为每一种资源都是由其XML元素所定义,所以你可以取任何你想要的文件名,并且添加不同类型的资源到同一个文件中。但是,为清楚起见,你应该把不同的资源放在不同的文件中。例如,以下是一些你可以使用的每一种资源对应的常用文件名:

  • arrays.xml 数组资源 (类型数组-typed arrays)
  • colors.xml 颜色-color values]
  • dimens.xml 维度-dimension values
  • strings.xml 字符串-string values
  • styles.xml 风格-styles
    详见字符串资源-String Resources, 风格资源Style Resource,以及更多资源类型-More Resource Types.
xml/任意的XML文件,能在运行时被Resources.getXML()调用。各种XML的配置文件必需存放在此,如:可搜索配置-searchable Configuration。
  • 注意:请勿将任何资源文件直接保存在res/路径下——这将导致编译错误。

更多关于各类资源的信息,请查看资源类型-Resource Types文档。

所有保存在表1中提到的子路径下的资源都是你的“默认”资源。也就是说,这些资为你的应用程序定义了默认的设计和内容。但是不同类型的Android设备,可能会要求不同类型的资源。例如,某个设备有一个比一般设备更大的屏幕,那你应该提供不同的布局资源来充分利用额外的屏幕空间。或是某个设备使用了一个不同的语言设置,那你应该提供一个可替代资源来翻译你的用户接口中的字符串资源。为不同设备配置提供不同的资源,你需要在默认资源之外,提供一些可选资源。

提供备选资源-Providing Alternative Resources

几乎所有的应用都应该提供备选资源来支持特定的设备配置。比如,你应该为不同的屏幕密度提供备选的绘图资源,为不同的语言提供不备选的字符串资源。Android将检测当前的设备配置,为你的应用加载适当的资源。

resource_devices_diagram2.png

图1 两个不同的设备,使用不同的布局资源

指定一系列特殊配置备选资源:

1.在res/路径下,以<资源名><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 and MNC如:

mcc310
mcc310-mnc004
mcc208-mnc00

移动手机国家区号(MCC),排在移动网络代码(MNC)之前。MNC来自设备的SIM卡。比如:mcc310表示美国,任何运营商;mcc310-mnc004表示美国Verizon;mcc208-mnc00表示法国Orange.

如果设备使用无线电连接(GSM手机),那么MCC和MNC的值来自于SIM卡。

你也可以只使用MCC(例如:你的应用中包含了某个指定国家的合法资源)。如果你只是需要指定不同的语言,那么请使用语言和区域修饰语(见下文)。如果你决定使用MCC和MNC修饰语,你应该仔细的做一些测试以保证其正常工作。

你也可以参与配置域mcc和mnc,他们分别指示了当前的移动手机国家区号和移动网络代码。

语言和区域<Language and region>如:

en
fr
en-rUS
fr-rFR
fr-rCA

语言由两个ISO 639-1语言代码组成,后面可以跟着两个由<ISO 3166-1-alpha-2>定义的区域代码字母(前面加小写字母“r”)。

这些代码不区分大小写,前缀“r”是用来区分区域代码的部分。你不前单独使用区域代码。

在应用程序的运行生命周期中,如果用户更改了他的系统语言设定,这些设置可以被更改。详见运行时变化处理- Handling Runtime Changes,了解其在运行时将怎么样影响你的应用程序。

查看定位-Localization完整向导,了解怎样根据其他言语定位你的应用程序。

同样可见locale配置域,其指示了当前的定位。

最小宽度<smallestWidth>sw<N>dp

如:
sw320dp
sw600dp
sw720dp
等.

屏幕的基本尺寸,由可用屏幕区域最短的尺寸决定。特别地,设备的最小宽度<smallestWidth>是指屏幕可用的高度和宽度中最短的那个(你也可以认为是一个屏幕“最短可能的宽度”)。你使用这个修饰语,可以保证,在不考虑当前屏幕方向的的情况下,你的应用程序至少拥有<N> dps的宽度供其UI使用。

比如,你的布局始终要求屏幕最小尺寸不少于600 dp,那么,你就可以使用这个修饰语创建一下布局资源,res/layout-sw600dp/。系统只会在最短的屏幕可能尺寸不少于600dp时使用这个资源,而不会去考虑600dp到底是高还是宽。最小宽度<smallestWidth>是一个确定的设备屏幕尺寸的特性;设备的最小宽度并不会因为屏幕的方向改变而改变

设备的最小宽度<smallestWidth>需要考虑屏幕的装饰和系统的UI。例如,如果设备在屏幕上有一些固定的UI元素,需要战胜最小宽度<smallestWidth>轴上的空间,系统将申明最小宽度<smallestWidth>小于实际的屏幕尺寸,因为那些屏幕像素对于你的UI来说不可用。另外,你使用的数值应该是确切的你的布局所需要的最小尺寸(一般来说,这个值是你的布局所支持的“最小的宽度”,无需考虑屏幕当前的方向)

你可能使用到的一些通用的屏幕尺寸值:

  • 320,设备的屏幕配置如下:
    • 240x320 ldpi (QVGA 手机)
    • 320x480 mdpi (手机)
    • 480x800 hdpi (高密度手机)
  • 480, 屏幕尺寸: 480x800 mdpi (平板电脑/手机)
  • 600, 屏幕尺寸: 600x1024 mdpi (7寸平板电脑)
  • 720, 屏幕尺寸: 720x1280 mdpi (10寸平板电脑)

当你的应用程序提供了不同的最小宽度<smallestWidth>修饰语,放在多资源路径下时,系统将使用最接近(但不超过)设备的最小宽度<smallestWidth>

在API level 13中加入

也可见android:requiresSmallestWidthDp属性,申明了你的应用程序所兼容的最小的最小宽度<smallestWidth>值;及smallestScreenWidthDp配置域,设置了设备的最小宽度<smallestWidth>值。

更多的关于不同屏幕设计和这个修饰语使用的信息,请见Supporting Multiple Screens开发者向导。

可用宽度<Available width>w<N>dp

如: w720dp w1024dp 等.

指定了一个最小的屏幕可用宽度,单位应该使用dp,能过<N>的值来定义。这个配置的值将会随着横屏和竖屏的转换而发生变化来匹配当前的实际宽度。


当你的应用程序为这个配置提供了不同的值并且放在多个资源路径下时,系统将会使用最接近(但不超过)设备当前的屏幕宽度。这个值需考虑屏幕的装饰,所以如果一个设备有一些固定的UT元素显示在左边缘或右边缘,它将使用一个比真实屏幕更小的宽度,考虑这些UI元素,并减小了应用的可用空间。 

在API level 13中加入。 

见screenWidthDp配置域,其设置了当前屏幕的宽度。 

更多的关于不同屏幕设计和这个修饰语使用的信息,请见Supporting Multiple Screens开发者向导。

可用高度<Available height>h<N>dp


如: h720dp h1024dp 等.

指定了一个最小的屏幕可用高度。单位应该使用dp,能过<N>的值来定义。这个配置的值将会随着横屏和竖屏的转换而发生变化来匹配当前的实际高度。


当你的应用程序为这个配置提供了不同的值并且放在多个资源路径下时,系统将会使用最接近(但不超过)设备当前的屏幕高度。这个值需考虑屏幕的装饰,所以如果一个设备有一些固定的UT元素显示在左边缘或右边缘,它将使用一个比真实屏幕更小的高度,考虑这些UI元素,并减小了应用的可用空间。不是固定不变的屏幕装饰(如屏幕状态条在全屏时可以被隐藏)不在这个考虑范围,窗口装饰如标题栏和工具栏等也不在考虑范围内,所以应用程序应该准备好处理一些比他们设定的更小的空间。 

在API level 13中加入。 

见screenHeightDp配置域,其设置了当前屏幕的宽度。 

更多的关于不同屏幕设计和这个修饰语使用的信息,请见Supporting Multiple Screens开发者向导。

屏幕尺寸<Screen size>small

normal large xlarge

small:类似于低密度的QVGA屏幕的尺寸。小屏幕的最小布局尺寸约为320x426 dp。如QVGA低密度和VGA高密度。

normal:类似于中等密度的HVGA屏幕尺寸。一般屏幕的最小布局尺寸约340x470 dp。如WQVGA低密度,HVGA中等密度,WVGA高密度。 

large:类似于中等密度的VGA屏幕尺寸。大屏幕的最小布局尺寸约480x640 dp。如中等密度的VGA和WVGA屏幕。 

xlarge:那些比传统中等密度HVGA更大的屏幕。加大屏幕的最小布局尺寸约720x960 dp。大多数情况下,加大屏幕的设备因为屏幕过大而无法放放口袋,一般为平板电脑类的设备。在API level 9中加入。 

  • 注解:使用某一个尺寸的修饰语并不代表资源只能被这种尺寸的屏幕使用。如果你提供的备选资源描述不能很好的与当前设备的配置匹配,而系统前选取其中最佳的那个资源。
  • 注意:如果你的所有资源都使用了一个比当屏幕更大的尺寸修饰语,系统将不会使用任何一个资源,你的应用程序将在运行里崩溃(如:如果所有的资源都被标上了xlarger,但设备是一个普通尺寸的屏幕。)


在API level 4中加入。 

更多信息,请见Supporting Multiple Screens开发者向导。 

见screenLayout配置域,其中指示了屏幕是否为大,中或小。

屏幕<Screen aspect>long

notlong

long: 长屏幕, 如:WQVGA, WVGA, FWVGA

notlong: 非长屏幕,如:QVGA, HVGA, and VGA 

在API level 4中加入

这个主要是基于屏幕的比例(“长”屏幕更宽一些)。和屏幕的方向无关。 

见screenLayout配置域,指示了屏幕是否为长屏幕。

屏幕方向<Screen orientation>port

land

port: 竖屏 (垂直方向的)

land: 横屏 (水平方向的) 

在应用程序的生命周期中这个配置会随着用户旋转屏幕而发生改变。详见运行时变化处理- Handling Runtime Changes,了解其在运行时将怎么样影响你的应用程序。

见orientation配置域,指示了,设备当前的方向。

停靠模式<Dock mode>car

desk

car: 设备在车中

desk: 设备在桌上 

在API level 8中加入。 

在应用程序生命周期中,这个配置会因为用户改变设备停放位置而发生改变。你可以通过UiModeManager启用或禁用这个模式。详见运行时变化处理- Handling Runtime Changes,了解其在运行时将怎么样影响你的应用程序。

夜间模式<Night mode>night

notnight

night: 夜间

notnight: 白天 

在API level 8中加入。 

在应用程序生命同期中,如果使用自动(默认)夜间模式,这个模式将会发生改变,即,这个模式会依据时间而改变。你可以通过UiModeManager启用或禁用这个模式。详见运行时变化处理- Handling Runtime Changes,了解其在运行时将怎么样影响你的应用程序。

屏幕像素密度<Screen pixel density> (dpi)ldpi

mdpi hdpi xhdpi nodpi tvdpi

ldpi: 低密度屏幕;约120dpi。

mdpi: 中等密度(传统的HVGA)屏幕;约160dpi。 hdpi: 高密度屏幕;约240dpi。xhdpi: 加高密度屏幕;约320dpi。在API level 8中加入。 nodpi: 这个可以用做位图资源,你不需要通过拉伸来匹配屏幕密度。 tvdpi: 屏幕在中等与高密度屏幕之间;约213dpi。这个不在首选的密度分组范围之内。这个主要是为电视和大部分不需要这个配置的应用准备的。对于很多应用,提供mdpi和hdpi资源都不能有效的匹配,系统会将它们拉伸到适合的大小。这个修饰语是在API level 13中加入的。 

在首选的密度中有一个3:4:6:8拉伸比例(不考虑tvdpi)。所以在ldpi中9x9的位图,在mdpi中为12x12,在hdpi中为18x18,在xhdpi中为24x24。 

如果你认为你的图片在电视或其他一些设备中效果不会很好,并且想尝试tvdpi资源,那么拉伸系数为1.33*mdpi。例如:在mdpi中一个100px x 100px的图像,在tvdpi中将为133px x 133px. 

  • 注解:使用一个密度修饰语并不表示这些资源只被用在指定的密度的屏幕中。如果你提供的可选资源和修饰语没有很好的匹配当前的设备配置,系统将会使用其中最好的那一个。



请见Supporting Multiple Screens,了解更多关于如何处理不同屏幕密度以及Android可能会拉伸你提供的位图来适应当前的密度。

触屏类型<Touchscreen type>notouch

stylus finger

notouch: 设备不支持触屏。

stylus: 设备有一个电阻式触屏,则适合使用stylus。
finger: 设备有一个触摸屏。 

同样可见touchscreen配置域,指示了设备的触屏类型。

键盘可用性<Keyboard availability>keysexposed

keyshidden keyssoft

keysexposed: 设备有一个可用键盘。如果设备有一个软键盘可用,这个配置也可用,即使是物理键盘没有暴露给用户,甚至设置没有物理键盘。如果没有软键盘盘如是被禁用,那个这配置只有在有物理键盘被暴露时可用。

keyshidden: 设备有一个物理键盘可用,但被隐藏了,且没有软键盘。 keyssoft: 设备有一个软键盘可以,不管其是否可见。 

如果你提供了一个keysexposed资源,但没有keyssoft资源,系统将使用keysexposed资源,而不考虑键盘是否可见,如果系统有一个软键盘可用。 

在应用程序的生命周期中这个配置会因用户打开一个物理键盘而发生改变。详见运行时变化处理- Handling Runtime Changes,了解其在运行时将怎么样影响你的应用程序。 

同样可见hardKeyboardHidden和keyboardHidden配置域,分别指示了物理键盘的可见性和任何键盘(包括软键盘)的可见性。

首选文本输入方法<Primary text input method>nokeys

qwerty 12key

nokeys: 设备没有物理键用作文本输入。

qwerty: 设备有一个物理的 qwerty 键盘,不管其是否对用户可见。 12key: 设备有一个物理的 12-key 键盘,不管其是否对用户可见。 

同样可见keyboard配置域,指示了可用的首选文本输入方法。

导航键可用性<Navigation key availability>navexposed

navhidden

navexposed: 导航键对用户可用。

navhidden: 导航键不可用(如:被盖子遮挡)。 

在应用程序生命周期中,这个配置会随着用户打开导航键而改变。见运行时变化处理- Handling Runtime Changes,了解其在运行时将怎么样影响你的应用程序。 

同样可见navigationHidden,指示了导航键是否被隐藏。

首选非触摸导航方式<Primary non-touch navigation method>nonav

dpad trackball wheel

nonav: 设备除了触摸屏没有导航设备。

dpad: 设备有一个directional-pad (d-pad)用来导航。
trackball: 设备有一个trackball用来导航.
wheel: 设备有一个directional wheel(s)用来导航(不常见)。 

同样可见navigation配置域,用来指示可用的导航方法类型。

平台版本<Platform Version> (API level)如:

v3 v4 v7 等。

设备所支持的。例如, v1 指API level 1 (设备为Android 1.0或更高版本) and v4 指 API level 4 (设备为 Android 1.6 或更高版本). 头天这个值的更多信息,请见Android API levels文档



  • 注意:Android 1.5和Android 1.6只有在资源的修饰语和版本号完全匹配时才能和这个资源匹配。更多信息,见后续章节已知问题- Known Issues。
  • 注解:有些配置修饰语在Android 1.0时就被加入了,所以并不是所有的Android版本都支持全部的修饰语。使用一个新的修饰语,隐藏的添加了版本号修饰语,让旧版本的设备忽略这个修饰语。例如:使用w600dp修饰语,将会自动添加v13修饰语,因为可用宽度修饰语在API level 13中被加入。为了避免任何问题,始终包含一系列默认资源(一系列没有修饰语的默认资源)。更多信息,见章节提供最好的设备兼容性与资源-Providing the Best Device Compatibility with Resources。

修饰语命名规则-Qualifier name rules

以下是一些关于使用配置修饰语命名的规则: 

  • 你可以为单独的一系列资源指定多个修饰语,用“-”分隔。如:为美式英语、水平方向的设备指定drawable-en-rUS-land
  • 修饰语必须按照表2中所列的顺序排序。如:
    • 错误:drawable-hdpi-port/
    • 正确:drawable-port-hdpi/
  • 可选资源的路径不能被嵌套。如,你不用这么使用res/drawable/drawable-en/
  • 修饰语的值不区分大小写。为了避免在大小写敏感的文件系统中出错,资源编译器在处理前会先将路径名全部转化会小写。名字中的任何大写字母只是为了有利于阅读。
  • 每一个修饰语类型中只有一个值被使用。例如,如果你想为西班牙和法国使用相同的绘图文件,你不能这样命名路径drawable-rES-rFR/。而是,你应该使用两个资源路径,如drawable-rES/drawable-rFR/,其中包含了恰当的内容。然后,你并不需要在两个路径中使用相同的文件。你可以为一个资源创建一个化名。见创建化名资源。


当你把资源保存在了这些以修饰语命名的路径中之后,Android自动的根据当前设备的配置来为你的应用提供合适的资源。每一次需要调用一个资源时,Android将检查包含被要求资源的可选资源路径,然后找到最佳资源(在下文讨论)。如果没有与特定设备配置所匹配的可选资源,那么,Android将使用默认资源(默认资源是指一系列特殊的没有设置配置修饰语的资源类型)。 

创建化名资源-Creating alias resources

当你有一个资源,想为多个设备配置使用(但不想作为默认资源提供)时,你不需要把一个相同的资源放在多个可选资源路径下。而是,你可以(在某些情况下)创建一个可选资源作为某个资源的化名保存在你的默认资源路径下。 

注解:不是所有资源都提供了这样的机制,能够为另一个资源创建一个化名。特别的:动画<animation>,菜单<menu>,raw,以及其他在xml/路径下的非特指的资源不提供这个功能。

例如,假设你有一个应用程序图标,icon.png需要为不同的地区指定唯一的版本。然后,两个地区,英国-加拿大人和法国-加拿大人,需要使用相同的版本。你也话会认为你需要拷贝同一个图片资源到英因-加拿大和法国-加拿大两个资源路径下,但这是不对的。而是,你可以把两个都使用到的图片资源保存为icon_ca.png(除了icon.png外的任何名字),并把他放在默认的res/drawable/路径下。然后在res/drawable-en-rCAres/drawable-fr-rCA创建一个icon.xml文件,使用<bitmap>元素指向icon_ca.png资源。这允话你保存一个版本的PNG文件和两个小的XML文件来指向它。(下面是一个XML文件的例子。) 

绘图-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

使用<include>元素为已存大的布局创建一个化名,包装在一个<merge>中 如:

 <?xml version="1.0" encoding="utf-8"?><merge>    <include layout="@layout/main_ltr"/></merge> 

如果你把这个文件保存为main.xml,那它将被编译成一个资源,你可以通过R.layout.main来引用,但实际上他是R.layout.main_ltr这个资源的化名。 

字条串和其他基本值-Strings and other simple values

为一个已存在的字符串创建一个化名,简单的使用想要的字符串的资源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的一个化名。 

其他的基本值-Other simple values使用方式相同。如,一个颜色值:

 <?xml version="1.0" encoding="utf-8"?><resources>    <color name="yellow">#f00</color>    <color name="highlight">@color/red</color></resources> 



提供最佳的设备与资源的兼容性-Providing the Best Device Compatibility with Resources

为了让你的应用程序支持多个设备配置,始终为你的应用中每一种资源都提供默认的资源是非常重要的。 

例如,如果你的应用程序支持多个语言,始终包括一个不含任何语言和区域修饰语的values/路径(其中保存了你用到的字符串)。如果你把所有的字符串都保存在带有语言和地区修饰语的路径下,那么如果一个设备设置了一个你的字符串不支持的语言和区域,你的应用程序将崩溃。但是,只要你提供了默认了的values/,那么你的应用将正常运行(即使是用户不懂这种语言,也好过于应用程序崩溃)。 

同样地,如果你根据屏幕的方向提供了不同的布局资源,你应该选择一个作为你的默认资源。如,在提供布局资源时,不是为横屏提供一个layout-land/,为竖屏提供一个layout-port/,而是要留一个作为默认资源,比如,横屏用layout/,竖屏用layout-port/。 

提供默认的资源很重要不仅仅因为你的应用程序可能会在一个你没有预想到的配置上运行,还因为新版本的Android有时候会添加一些老版本并不支持的新配置修饰语。如果你使用了一个新的资源修饰话,但你向老版本的Android兼容了你的代码,这样,当你的应用程序在一个老版本的Android设备上运行时,如果你没有提供默认的资源,其将崩溃,因为老版本的Android不能识别带有新修饰语的资源名。比如,你的[minSdkVersion]设置为4,而且你限制你所有的绘图资源使用夜间模式(nightnotnight(在API level 8中被加入),那么一个API level 4的设备就不能获取你的绘图资源,将会崩溃。在这种情况下,你大概想要notnight作为你的默认资源,所以你应该更改那个修饰语,将你的绘图资源放在drawable/drawable-night/中。 

所以,为了提供最好的设备兼容性,你应该总是为你的应用程序提供所需的默认资源,让其能正常运作。然后使用配置修饰语,为指定的设备配置创建可选资源。 

这个规则有一个例外:如果你应用程序的[minSdkVersion]为4或更大,当你使用屏幕密度修饰语提供可选的绘图资源时,你不需要默认资源。即使没有默认资源,Android也能在你提供的可选的屏幕密度中找到最佳匹配的资源,并把其拉伸为需要的位图。然而,为了在所有设备上达到最好的体验效果,为三种不同的密度提供可选择的绘图资源。如果你的[minSdkVersion]小于4(Android 1.5或更低版本),请注意,屏幕尺寸,密度和这方面的修饰语不支持Android 1.5或更低版本。你可能要为这些版本执行其他的兼容性措施。 


Android怎么样寻找最佳匹配资源-How Android Finds the Best-matching Resource

当你需要一个你提供的可选资源时,Android会根据当前的设备配置,在运行时来选择一个可选资源。为了展现Android怎么选择一个可选资源,假设下列绘图路径每一个都包含了不同版本的同一个图片:

res-selection-flowchart.png

图2 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/选择了了绘图。 

系统按照以下的逻辑来选择所要的资源:

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/
 

例外:屏幕像素密度这个修饰语i没有因矛盾而被排除。即使设备的屏幕密度是hdpi,但drawable-port-ldpi/没有被排除,因为这时,第一个屏幕密度都被认为是匹配的,更多我信息请见Supporting Multiple Screens文档。

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倾向于缩小一个更大的原始图片还不是拉伸更小的原始图片。见Supporting Multiple Screens。

5. 返回,重复第2,3和4步,直到只有一个路径剩下。在这个例子中,屏幕方向是下一个匹配的修饰语。所以没的指定屏幕方向的路径将被排除:

drawable-en/
drawable-en-port/
drawable-en-notouch-12key/

剩下drawable-en-port/路径

虽然这个处理流程查找了每一个要求的资源,但系统在一些方面做出了进一步的优化。其中一个优化是,一但这个设备配置已知,它将排除那些永远不能匹配的可选资源。例如,如果配置语言为英语(“en”),那么任意一个设置了除英语以外的语言修饰语的资源路径将不会再包括在被检测的资源池中(但是,没有设置语言修饰语的路径还被包括在内)。 

当选择基于屏幕尺寸修饰语的资源时,如果没有更好的匹配资源,系统将会使用一个比当前屏幕更小的资源(如,在需要的情况下,一个大尺寸<large-size>屏幕将会使用一个普通尺寸<normal-size>的屏幕资源)。但是,如果只有一个比当前屏幕更大的可用资源,系统将不会使用他们,如果没有其他资源与设备配置匹配,你的应用程序将会崩溃(例如,所有的布局资源都标着xlarger这个修饰语,但设备是一个普通尺寸<normal-size>的屏幕)。 

注解:修饰语的优先级(表2中所列)比与设备完全匹配的修饰语的数量更重要。如,在第4步中,列表中剩下的最后一个选项包含了三个与设备完全匹配的修饰语(方向<orientation>,触屏类型<touchscreen>,和输入方式<input method>),但drawable-en只有一个参数(语言)匹配。然而,语言拥有一个更高的优先级,所以drawable-por-notouch-12key被淘汰。

一旦你在你的应用程序中提供了一个资源(在资源提供-Providing Resources中讨论过),你可以通过引用它的资源ID来调用它。所有在工程项目中R class中定义的资源ID都是能过aapt自动生成的。

当你的应用程序被编译时,aapt生成了R class,其中包含了res/路径下所有资源的资源ID。对于每天种类型的资源,都有的一R subclass(子类)(如:R.drawable对应绘图<drawable>资源)并且对于每一种资源类型,都有一个静态整型常量(如,R.drawable.icon)。这个整型常量就是可以被用来调用资源的资源ID。

虽然资源ID是在R class中指定的,但你并不需要去那儿找资源ID。一个资源ID总是由以下部分组成:

  • 资源类型:每一个资源都是以某种“类型”分组的,如字符串<string>,绘图<drawable>,以及布局<layout>。更多的资源类型,请见资源类型-Resource Types。
  • 资源名:即文件名,包括其括展名;或者,如果资源只是一个基本类型值(如一个字符串<string>),则是在XML中android:name属性的值。


访问一个资源有两种方法:

  • 在代码中:使用一个R class子类中的一个静态整型值,如:

R.string.hello

string是资源类型,hello是资源名。当你提供一个这种格式的资源类型时,有很多的Android API可以访问你你的资源。见在代码中访问资源-Accessing Resources in Code。

  • 在XML中:使用一个特殊的XML语法,对应R class中定义的资源ID,如:

@string.hello
string是资源类型,hello是资源名。你可以在XML中任意一个需要的地方使用这个语法。见通过XML访问资源-Accessing Resources from XML。


在代码中访问资源-Accessing Resources in Code

你可以在代码中把资源ID传递给人个方法的参数来使用了一资源。例如,你可以通过setImageResource()设置一个ImageView来使用res/drawable/myimage.png资源:

访问原始文件

偶尔,你可能需要访问原始文件和路径。如果你这么做了,那么你保存在res/中的文件将不会为你所用,因为唯一一个读取res/中资源的方法就是通过其资源ID。不过,你可以把你的资源保存在assets/路径下。

被保存在assets/路径下的文件将不会得到一个资源ID,所以你不可以能过R class或是XML来引用它们。不过,你可以像普通的文件系统一样,查询assets/路径下的文件,并且使用AssetManager来读取原始的未经处理的数据。

然而,如果你所要求的是读取原始的未经处理的数据(如一个视频或音频文件),那么,把文件保存在res/raw/路径下,并通过openRawResource()来读取一个字节流。

 ImageView imageView = (ImageView) findViewById(R.id.myimageview);imageView.setImageResource(R.drawable.myimage)

你也要以使用Resources中的方法来检索独立的资源,使用getResources()来获得一个实例。

语法

这是在代码中引用一个资源的语法:

[<package_name>.]R.<resource_type>.<resource_name>

  • <package_name>是资源所在的包名(如果被引用的资源在你自己的包中,不需要指明)。
  • <resource_type>R的子类中资源的类型。
  • <resource_name>是不包括扩展名的资源文件名或XML元素中android:name属性的值(基本类型)。

使用案例

有很多种方法可以接受一个资源ID参数,你可以使用Resources中的方法来检索资源。你可以通过Context.getResources()来获得Resources的一个实例。

以下是在代码中访问资源的一些实例:

 // Load a background for the current screen from a drawable resourcegetWindow().setBackgroundDrawableResource(R.drawable.my_background_image) ; // Set the Activity title by getting a string from the Resources object, because//  this method requires a CharSequence rather than a resource IDgetWindow().setTitle(getResources().getText(R.string.main_title))// Load a custom layout for the current screensetContentView(R.layout.main_screen)// Set a slide in animation by getting an Animation from the Resources objectmFlipper.setInAnimation(AnimationUtils.loadAnimation(this,        R.anim.hyperspace_in))// Set the text on a TextView object using a resource IDTextView msgTextView = (TextView) findViewById(R.id.msg);msgTextView.setText(R.string.hello_message)


注意:你永远不要手动修改R.java文件——它是在项目被编译时由aapt生成的。任何的改变将在下一次编译时被重写。

通过XML访问资源-Accessing Resources from XML

你可以使用一个已存在的资源的引用来定义一些XML的属性和元素的值。当你创建布局文件时将会经常使用到这个方法为你的小部件提供字符串和图片。

例如,你为你的布局添加一个Button,你应该使用字符串资源-String Resources作为button的文字:

 <Button    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:text="@string/submit" /> 

语法

以下是XML中引用一个资源的语法:

@[<package_name>:]<resource_type>/<resource_name>

  • <package_name>是资源所在的包名(如果被引用的资源在你自己的包中,不需要指明)。
  • <resource_type>R的子类中资源的类型。
  • <resource_name>是不包括扩展名的资源文件名或XML元素中android:name属性的值(基本类型)。

更多关于怎么样引用每一种资源类型的信息,请见资源类型-Resource Types。

使用案例

在一些情况下,你必须使用一个资源作为XML中的一个值(如,为一个小部件提供一个图片),但是,你可以在XML中任意一个可以接受一个基本类型值的地方使用一个资源。例如,假如你有以下资源文件,包括了一个颜色启动和一个字符串资源:

 <?xml version="1.0" encoding="utf-8"?><resources>   <color name="opaque_red">#f00</color>   <string name="hello">Hello!</string></resources></xm> 你可以在以下的布局文件中使用这些资源来设置文本颜色和文本字符串:<br /> <xml><?xml version="1.0" encoding="utf-8"?><EditText xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:textColor="@color/opaque_red"    android:text="@string/hello" /> 

在这个案例中,在资源引用时,你不需要指名包名,因为这些资源来自于你自己的包。引用一个系统资源,你需要包括一个包名。如:

 <?xml version="1.0" encoding="utf-8"?><EditText xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:textColor="@android:color/secondary_text_dark"    android:text="@string/hello" /> 

注解:你应该始终都可以使用用字符串资源,这样你的应用就可以被其他语言定位。更多的关于创建可选资源(如可本地化的字符串),见提供可选资源-Providing Alternative Resources

你甚至可以在XML中创建化名。例如,你可以创建一个绘图资源,作为另一个绘图资源的化名:

 <?xml version="1.0" encoding="utf-8"?><bitmap xmlns:android="http://schemas.android.com/apk/res/android"    android:src="@drawable/other_drawable" /> 

这个听起来无用,但在使用可选资源时将会非常有用。更多请见创建化名资源-Creating alias resources

引用样式属性-Referencing style attributes

一个样式属性资源允许你引用一个当前使用主题中某个属性的值。引用一个样式属性允许你定制UI元素的外观,通过样式化他们来匹配当前主题提供的标准化的变化,而不是提供一个硬编码值。引用一个样式属性本质上说的是,“在当前主题下,使用一个被这个属性所定义的样式。”

引用一个样式属性,其命名的语法几乎是与一般资源的格式相同,但是,使用一个问号(?)来替代@符号,并且资源类型部分是可选的。如:

?[<package_name>:][<resource_type>/]<resource_name>

例如,这里是一个例子,展示了如何引用一个属性来设定文本颜色以匹配系统主题“主要的”文本颜色:

 <EditText id="text"    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:textColor="?android:textColorSecondary"    android:text="@string/hello_world" /> 

其中,android:textColor属性指定了当前主题中,一个样式属性的名字。在这个小部件中,Android将使用android:textColorSecondary样式属性的值作为android:textColor的值。因为系统资源工具知道,在这个环境下需要一个属性资源,你并不需要明确的指定其类型(需要可以这样定义?android:attr/textColorSecondary)-你可以排除attr类型。

访问平台资源-Accessing Platform Resources

Android包含了很多标准化资源,如,样式、主题和布局。要访问这些资源,在你的资源引用中需要包括其android包名。例如,在ListAdapter中,Android提供了一个你可以用作列举项目的布局资源:

 setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myarray))

在这个范例中,simple_list_item_1是一个布局资源,在ListView中,为了项目由平台所定义。你可以使用这个资源而不用创建一个自己的布局来列举项目。(更多关于如何使用ListView,请见List View Tutorial。)


0 0