第三部分:Android 应用程序接口指南---第三节:应用程序资源---第一章 资源提供
第1章 资源提供
你应该经常外部化你应用程序代码中的资源,比如图片、字符串等,这样有利于你独立处理这些资源。你也应该根据特定的设备配置提供一些可替代的资源,并且把他们分组保存在指定的路径名下。运行时,Android可以根据当前的配置使用适当的资源。比如,你也许会根据不同的屏幕尺寸提供不同的UI布局或是不同的语言设定提供不同的字符串。一旦你外部化了应用程序中的资源,你就能通过项目中的R类<class>生成的ID来调用他们。本章将向你展示怎么样分类你Android项目中的资源,以及怎么样给特定的设备配置提供可替代的资源。
1.1 资源类型分组
你应该把每一种类型的资源分别放在你的项目中res/中特定的子路径下。这是一个简单的项目中,文件分层的例子:
MyProject/
src/
MyActivity.java
res/
drawable/
icon.png
layout/
main.xml
info.xml
values/
strings.xml
从这个例子中你可以看到,res/路径下包含了所有类型的资源(在每一个子路径中):一个图片资源,两个布局资源和一个字符串资源文档。资源路径名非常重要,并在表1-1中做了具体描述。
路径 |
资源 |
animator/ |
XML文件,定义了属性动画(property animations) |
anim/ |
XML文件,定义了渐变动画(tween animations) (属性动画(property animations)也能保存在这个路径下, 但animator/路径是专为属性动画(property animations)准备的,用来区别这两种类型的动画) |
color/ |
XML文件,定义了一个颜色状态列表 |
drawable/ |
位图(.png, .9.png, .jpg, .gif)或XML文件,编译成以下绘图资源子类型: 位图文件(Bitmap files) Nine-Patches (尺寸可变的位图) 状态列表(State lists) 形状(Shapes) 动画drawables(Animation drawables) 其它drawables |
layout/ |
XML文件,定义了用户接口布局 |
menu/ |
XML文件,定义了应用程序的菜单,如选择菜单<Options Menu>,快捷菜单<Context Menu>和子菜单 |
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资源。 arrays.xml数组资源 (类型数组-typed arrays) colors.xml--color values dimens.xml--dimension values strings.xml--string values styles.xml--styles |
xml/ |
任意的XML文件,能在运行时被Resources.getXML()调用。各种XML的配置文件必需存放在此,如:可搜索配置-searchable |
表1-1 项目res/下支持的资源目录(注意:请勿将任何资源文件直接保存在res/路径下——这将导致编译错误。)
所有保存在表1-1中提到的子路径下的资源都是你的“默认”资源。也就是说,这些资为你的应用程序定义了默认的设计和内容。但是不同类型的Android设备,可能会要求不同类型的资源。例如,某个设备有一个比一般设备更大的屏幕,那你应该提供不同的布局资源来充分利用额外的屏幕空间。或是某个设备使用了一个不同的语言设置,那你应该提供一个可替代资源来翻译你的用户接口中的字符串资源。为不同设备配置提供不同的资源,你需要在默认资源之外,提供一些可选资源。
1.2 提供可选的资源
几乎所有的应用都应该提供可选资源来支持特定的设备配置。比如,你应该为不同的屏幕密度提供可选的绘图资源,为不同的语言提供可选的字符串资源。Android将检测当前的设备配置,为你的应用加载适当的资源。
图1-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支持几种配置后缀,你可以添加多个后缀到同一个路径名,通过‘_’来分隔每一个后缀。表1-2列举了可用的配置后缀,考虑优先级,如果你为同一个资源路径使用了多个后缀,你应该按照表中的列举的顺序添加。
配置 |
后缀值 |
描述 |
MCC和MNC |
如: mcc310 |
移动手机国家区号(MCC),排在移动网络代码(MNC)之前。MNC来自设备的SIM卡。比如:mcc310表示美国任意运营商;mcc310-mnc004表示美国Verizon公司(美国一家无线营运商);mcc208-mnc00表示法国Orange. 如果设备使用无线电连接(GSM手机),那么MCC和MNC的值来自于SIM卡。 你也可以只使用MCC(例如:你的应用中包含了某个指定国家的合法资源)。如果你只是需要指定不同的语言,那么请使用语言和区域后缀(见下文)。如果你决定使用MCC和MNC后缀,你应该仔细的做一些测试以保证其正常工作。 你也可以参与配置域mcc和mnc,他们分别指示了当前的移动手机国家区号和移动网络代码。 |
语言和区域 |
如: en |
语言由两个ISO 639-1语言代码组成,后面可以跟着两个由<ISO 这些代码不区分大小写,前缀“r”是用来区分区域代码的部分。你不前单独使用区域代码。 在应用程序的运行生命周期中,如果用户更改了他的系统语言设定,这些设置可以被更改。 同样可见locale配置域,其指示了当前的定位。 |
布局方向 |
ldrtl ldltr |
应用程序的布局方向。 ldrtl的意思是“布局方向从右至左”。 ldltr意味着“布局方向左到右”,ldltr是默认值。 这可以适用于任何资源,如layouts,drawables,or values。 例如,如果你想提供一些具体的布局,阿拉伯语和一些通用的布局,任何其他“从右至左”语言(象波斯或希伯来文),那么你会: res/ layout/ main.xml中(默认布局) layout-ar/main.xml的(指定布局阿拉伯语-Arabic) layout-ldrtl/main.xml中(任何“从右到左”的语言,除了阿拉伯语,因为“ar”的语言预选项具有更高的优先级。) 注意:这是API 17的新功能,要启用从右到左的布局功能,为您的应用程序,你必须设置supportsRtl为“true”,“targetSdkVersion”设置为17或更高。 |
最小宽度 |
sw<N>dp 如: |
屏幕的基本尺寸,由可用屏幕区域最短的尺寸决定。设备的最小宽度<smallestWidth>是指屏幕可用的高度和宽度中最短的那个(你也可以认为是一个屏幕“最短可能的宽度”)。你使用这个后缀,可以保证,在不考虑当前屏幕方向的的情况下,你的应用程序至少拥有<N>dp的宽度供其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>值。 |
可用宽度<Available width> |
w<N>dp 如: w720dp w1024dp等 |
指定了一个最小的屏幕可用宽度,单位应该使用dp,能过<N>的值来定义。这个配置的值将会随着横屏和竖屏的转换而发生变化来匹配当前的实际宽度。 当你的应用程序为这个配置提供了不同的值并且放在多个资源路径下时,系统将会使用最接近(但不超过)设备当前的屏幕宽度。这个值需考虑屏幕的装饰,所以如果一个设备有一些固定的UT元素显示在左边缘或右边缘,它将使用一个比真实屏幕更小的宽度,考虑这些UI元素,并减小了应用的可用空间。 在API level 13中加入。 见screenWidthDp配置域,其设置了当前屏幕的宽度。 |
可用高度<Available height> |
h<N>dp 如: h720dp h1024dp 等 |
指定了一个最小的屏幕可用高度。单位应该使用dp,能过<N>的值来定义。这个配置的值将会随着横屏和竖屏的转换而发生变化来匹配当前的实际高度。 当你的应用程序为这个配置提供了不同的值并且放在多个资源路径下时,系统将会使用最接近(但不超过)设备当前的屏幕高度。这个值需考虑屏幕的装饰,所以如果一个设备有一些固定的UT元素显示在左边缘或右边缘,它将使用一个比真实屏幕更小的高度,考虑这些UI元素,并减小了应用的可用空间。不是固定不变的屏幕装饰(如屏幕状态条在全屏时可以被隐藏)不在这个考虑范围,窗口装饰如标题栏和工具栏等也不在考虑范围内,所以应用程序应该准备好处理一些比他们设定的更小的空间。 在API level 13中加入。 见screenHeightDp配置域,其设置了当前屏幕的宽度。 |
屏幕尺寸<Screen size> |
small normal large xlarge |
small:类似于低密度的QVGA屏幕的尺寸。小屏幕的最小布局尺寸约为320x426 normal:类似于中等密度的HVGA屏幕尺寸。一般屏幕的最小布局尺寸约340x470 large:类似于中等密度的VGA屏幕尺寸。大屏幕的最小布局尺寸约480x640 xlarge:那些比传统中等密度HVGA更大的屏幕。加大屏幕的最小布局尺寸约720x960 注解:使用某一个尺寸的后缀并不代表资源只能被这种尺寸的屏幕使用。如果你提供的备选资源描述不能很好的与当前设备的配置匹配,而系统前选取其中最佳的那个资源。 注意:如果你的所有资源都使用了一个比当屏幕更大的尺寸后缀,系统将不会使用任何一个资源,你的应用程序将在运行里崩溃(如:如果所有的资源都被标上了xlarger,但设备是一个普通尺寸的屏幕。) 在API level 4中加入。 |
屏幕朝向 |
long notlong |
long:长屏幕,如:WQVGA,WVGA,FWVGA notlong:非长屏幕,如:QVGA,HVGA, VGA 在API level 4中加入。 这个主要是基于屏幕的比例(“长”屏幕更宽一些)。和屏幕的方向无关。 |
屏幕方向 |
port land |
port: 竖屏 (垂直方向的) land: 横屏 (水平方向的) 在应用程序的生命周期中这个配置会随着用户旋转屏幕而发生改变。 |
UI模式 |
car desk television appliance |
car: 设备在车中显示 desk: 设备在桌上显示 television:设备在电视机上显示“十英尺”的体验,它的用户界面是在大屏幕上,用户很远,主要是面向,周围的DPAD或其他非指针互动。 Appliance: 设备是作为一个器械,没有显示。 在应用程序生命周期中,这个配置会因为用户改变设备停放位置而发生改变。你可以通过UiModeManager启用或禁用这个模式。 在API level 8中加入 Television在API level 13加入 |
夜间模式 |
night notnight |
night: 夜间 notnight: 白天 在API level 8中加入。 在应用程序生命同期中,如果使用自动(默认)夜间模式,这个模式将会发生改变,即,这个模式会依据时间而改变。你可以通过UiModeManager启用或禁用这个模式。 |
屏幕像素密度(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. 注解:使用一个密度后缀并不表示这些资源只被用在指定的密度的屏幕中。如果你提供的可选资源和后缀没有很好的匹配当前的设备配置,系统将会使用其中最好的那一个。 |
触屏类型 |
notouch finger |
notouch:设备不支持触屏。 |
键盘可用性 |
keysexposed keyshidden keyssoft |
keysexposed: 设备有一个可用键盘。如果设备有一个软键盘可用,这个配置也可用,即使是物理键盘没有暴露给用户,甚至设置没有物理键盘。如果没有软键盘被禁用,那个这配置只有在有物理键盘被暴露时可用。 keyshidden: 设备有一个物理键盘可用,但被隐藏了,且没有软键盘。 keyssoft: 设备有一个软键盘可以用,不管其是否可见。 如果你提供了一个keysexposed资源,但没有keyssoft资源,系统将使用keysexposed资源,而不考虑键盘是否可见,如果系统有一个软键盘可用。 在应用程序的生命周期中这个配置会因用户打开一个物理键盘而发生改变。 |
首选文本输入方法 |
nokeys:设备没有物理键用作文本输入。 qwerty:设备有一个物理的qwerty 键盘,不管其是否对用户可见。 12key:设备有一个物理的12-key键盘,不管其是否对用户可见。 |
|
导航键可用性 |
navexposed navhidden |
navexposed:导航键对用户可用。 navhidden:导航键不可用(如:被盖子遮挡)。 |
首选非触摸导航方式 |
nonav dpad trackball wheel |
nonav: 设备除了触摸屏没有导航设备。 dpad: 设备有一个directional-pad (d-pad)用来导航。 |
平台版本(API Level) |
如: v3 v4 v7等。 |
设备所支持的。例如, v1 指API level v4 指 API level 4 (设备为 Android 1.6 或更高版本) |
表1-2 配置后缀详解
注意:有些配置后缀在Android 1.0时就被加入了,所以并不是所有的Android版本都支持全部的后缀。使用一个新的后缀,隐藏的添加了版本号后缀,让旧版本的设备忽略这个后缀。例如:使用w600dp后缀,将会自动添加v13后缀,因为可用宽度后缀在API level 13中被加入。为了避免任何问题,始终包含一系列默认资源(一系列没有后缀的默认资源)。
1.2.1后缀命名规则
以下是一些关于使用配置后缀命名的规则:
◆你可以为单独的一系列资源指定多个后缀,用“-”分隔。如:美式英语、水平方向的设备指定drawable-en-rUS-land。
◆后缀必须按照表1-2中所列的顺序排序。如:
错误:drawable-hdpi-port/
正确:drawable-port-hdpi/
◆可选资源的路径不能被嵌套。如,你不用这么使用res/drawable/drawable-en/
◆后缀的值不区分大小写。为了避免在大小写敏感的文件系统中出错,资源编译器在处理前会先将路径名全部转化会小写。名字中的任何大写字母只是为了有利于阅读。
◆每一个后缀类型中只有一个值被使用。例如,如果你想为西班牙和法国使用相同的绘图文件,你不能这样命名路径drawable-rES-rFR/。而是,你应该使用两个资源路径,如drawable-rES/和drawable-rFR/,其中包含了恰当的内容。然后,你并不需要在两个路径中使用相同的文件。你可以为一个资源创建一个化名。
当你把资源保存在了这些以后缀命名的路径中之后,Android自动的根据当前设备的配置来为你的应用提供合适的资源。每一次需要调用一个资源时,Android将检查包含被要求资源的可选资源路径,然后找到最佳资源(在下文讨论)。如果没有与特定设备配置所匹配的可选资源,那么,Android将使用默认资源(默认资源是指一系列特殊的没有设置配置后缀的资源类型)。
1.2.2创建资源别名
当你有一个资源,想为多个设备配置使用(但不想作为默认资源提供)时,你不需要把一个相同的资源放在多个可选资源路径下。而是,你可以(在某些情况下)创建一个可选资源作为某个资源的别名保存在你的默认资源路径下。
注意:不是所有资源都提供了这样的机制,能够为另一个资源创建一个别名。如:动画<animation>,菜单<menu>,raw,其他在非xml/路径下的资源不提供这个功能。
例如,假设你有一个应用程序图标,icon.png需要为不同的地区指定唯一的版本。然后,两个地区,英国-加拿大人和法国-加拿大人,需要使用相同的版本。你也许会认为你需要拷贝同一个图片资源到英因-加拿大和法国-加拿大两个资源路径下,但这是不对的。而是,你可以把两个图片资源保存为icon_ca.pan(除了icon.png外的任何名字),并把他放在默认的res/drawable/路径下。然后在res/drawable-en-rCA和res/drawable-fr-rCA创建一个icon.xml文件,使用<bitmap>元素指向icon_ca.png资源。这允话你保存一个版本的PNG文件和两个小的XML文件来指向它。(下面是一个XML文件的例子。)
Drawable
使用<bitmap>元素为一个已存在的绘图文件创建一个别名。如代码清单1-1所示:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/icon_ca" />
代码清单1-1
如果把这个文件保存为icon.xml(在可选资源路径下,如res/drawable-en-rCA/),它将被编译成一个资源,你可以通过R.drawable.icon来引用,但它实际上是R.drawable.icon_ca的别名(被保存在res/drawable/)。
Layout
使用<include>元素为已存大的布局创建一个化名,包装在一个<merge>中 如代码清单1-2所示:
<?xml version="1.0" encoding="utf-8"?>
<merge>
<include layout="@layout/main_ltr"/>
</merge>
代码清单1-2
如果你把这个文件保存为main.xml,那它将被编译成一个资源,你可以通过R.layout.main来引用,但实际上他是R.layout.main_ltr这个资源的别名。
字条串和其他基本值
为一个已存在的字符串创建一个别名,简单的使用想要的字符串的资源ID作为一个新字符串的值。如代码清单1-3所示:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello</string>
<string name="hi">@string/hello</string>
</resources>
代码清单1-3
现在R.string.hi资源是R.string.hello的一个别名。
其他的基本值使用方式相同。如,一个颜色值,像代码清单1-4所示:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="yellow">#f00</color>
<color name="highlight">@color/red</color>
</resources>
代码清单1-4
1.3 提供设备与资源的最佳兼容性
为了让你的应用程序支持多个设备配置,始终为你的应用中每一种资源都提供默认的资源是非常重要的。 例如,如果你的应用程序支持多个语言,始终包括一个不含任何语言和区域后缀的values/路径(其中保存了你用到的字符串)。如果你把所有的字符串都保存在带有语言和地区后缀的路径下,那么如果一个设备设置了一个你的字符串不支持的语言和区域,你的应用程序将崩溃。但是,只要你提供了默认了的values/,那么你的应用将正常运行(即使是用户不懂这种语言,也好过于应用程序崩溃)。同样地,如果你根据屏幕的方向提供了不同的布局资源,你应该选择一个作为你的默认资源。如,在提供布局资源时,不是为横屏提供一个layout-land/,为竖屏提供一个layout-port/,而是要留一个作为默认资源,比如,横屏用layout/,竖屏用layout-port/。
提供默认的资源很重要不仅仅因为你的应用程序可能会在一个你没有预想到的配置上运行,还因为新版本的Android有时候会添加一些老版本并不支持的新配置后缀。如果你使用了一个新的资源修饰话,但你向老版本的Android兼容了你的代码,这样,当你的应用程序在一个老版本的Android设备上运行时,如果你没有提供默认的资源,就会崩溃,因为老版本的Android不能识别带有新后缀的资源名。比如,你的minSdkVersion设置为4,并且你限制你所有的绘图资源使用夜间模式(night和notnight(在API level 8中被加入),那么一个API level 4的设备就不能获取你的绘图资源,将会崩溃。在这种情况下,你大概想要notnight作为你的默认资源,所以你应该更改那个后缀,将你的绘图资源放在drawable/或drawable-night/中。
所以,为了提供最好的设备兼容性,你应该总是为你的应用程序提供所需的默认资源,让其能正常运作。然后使用配置后缀,为指定的设备配置创建可选资源。
这个规则有一个例外:如果你应用程序的minSdkVersion为4或更大,当你使用屏幕密度后缀提供可选的绘图资源时,你不需要默认资源。即使没有默认资源,Android也能在你提供的可选的屏幕密度中找到最佳匹配的资源,并把其拉伸为需要的位图。然而,为了在所有设备上达到最好的体验效果,最好为三种不同的密度提供可选择的绘图资源。如果你的minSdkVersion小于4(Android 1.5或更低版本),请注意,屏幕尺寸,密度和这方面的后缀不支持Android 1.5或更低版本。你可能要为这些版本执行其他的兼容性措施。
1.3.1为Android1.5提供屏幕资源的兼容性
Android 1.5(和更低版本)不支持以下的配置后缀:
密度(Density)
ldpi, mdpi, ldpi,和nodpi,
屏幕尺寸(Screen size)
small,normal,和large
屏幕朝向(Screen aspect)
long,和notlong
这些配置后缀是在Android 1.6中加入的,所以Android 1.5(API level 3)和更低版本并不支持。如果你使用了这些配置后缀,但没有提供对应的默认资源,那么Android 1.5的设备可能使用这些后缀命名的任何一个资源,因为它无视这些后缀,而会使用在其它方面找到的第一个匹配的绘图资源。例如,你的应用程序支持Android 1.5,并且包含了各种屏幕密度的绘图资源(drawable-ldpi/, drawable-mdpi/,和drawable-ldpi/),但不包括默认绘图资源(drawable/),那么Android 1.5 将会使用可选资源路径下的任何一个资源,这可能导致用户界面达不到理想的要求。
所以为Android 1.5(和更低版本)提供兼容性时,使用以下屏幕配置后缀:
1. 为中等密度<medium-density>,普通<normal>和非长<not-long>的屏幕提供默认资源。
因为所有的Android 1.5设备都有中等密度< medium -density>,普通<normal>和非长<not-long>这种的屏幕,你可以提供这们的资源放在对应的默认资源路径中。如,把所用中等密度的绘图资源都放在drawable/路径下,(而不是drawable-mdpi/),把所有普通<normal>尺寸的资源放在对应的默认资源路径下,以及非长<notlong>资源放在对应的默认资源路径下。
2. 确保你的SDK Tools版本为r6或更高版本。
你需要SDK Tools,版本6(或更高版本),因为它包含了新的自动打包工具,为每一个使用了,在Android 1.0时不存在的后缀命名的资源路径名,自动添加一个适合和版本后缀。如,因为密度后缀在Android 1.6(API level 4)时被引入的,当打包工具遇到一个使用了密度后缀的资源路径时,它在路径名中添加了v4 以确保老版本不使用这些资源(只有API level 4以及更高版本支持后缀)。另外,把中等密度的资源放在一个没有mdpi后缀的路径下,它们同样能被Android 1.5读取,并且任何支持密度后缀并拥有中等密度屏幕也会使用默认资源(也就是mdpi),因为他们会选择与设置最佳匹配的资源(而不是使用ldpi或hdpi资源)。
注意:Android更新的版本,如API level 8,引入了老版本不支持的其它配置后缀。为了提供最佳的兼容性,你应该为你的应用程序所用到的各种资源提供一系列的默认资源,正如之前讨论的,为了提供最佳的设备兼容性。
1.4 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 typ)
= notouch
首选文本输入方法(Primary text input method) = 12key
通过对比设备配置和可能的备选资源,Android从drawable-en-port/选择了drawables。
系统按照以下的逻辑来选择所要的资源:
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. 取(下一个)根据(表1-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”),那么任意一个设置了除英语以外的语言后缀的资源路径将不会再包括在被检测的资源池中(但是,没有设置语言后缀的路径还被包括在内)。
当选择基于屏幕尺寸后缀的资源时,如果没有更好的匹配资源,系统将会使用一个比当前屏幕更小的资源(如,在需要的情况下,一个大尺寸<large-size>屏幕将会使用一个普通尺寸<normal-size>的屏幕资源)。但是,如果只有一个比当前屏幕更大的可用资源,系统将不会使用他们,如果没有其他资源与设备配置匹配,你的应用程序将会崩溃(例如,所有的布局资源都标着xlarger这个后缀,但设备是一个普通尺寸<normal-size>的屏幕)。
注意:后缀的优先级(表2中所列)比与设备完全匹配的后缀的数量更重要。如,在第4步中,列表中剩下的最后一个选项包含了三个与设备完全匹配的后缀(方向<orientation>,触屏类型<touchscreen>,和输入方式<input method>),但drawable-en只有一个参数(语言)匹配。然而,语言拥有一个更高的优先级,所以drawable-port-notouch-12key被淘汰。
1.5 已知问题
Android
1.5和1.6:版本后缀必需完全匹配还不是最佳匹配。
正确的做法是,系统匹配标记了相等或低于设备平台版本的版本后缀的资源,但是对于Android 1.5和1.6,(API
level 3和4),有一个bug,引起了系统只能匹配标记了与设备版本完全相同的后缀的资源。
变通方法:提供一个特定版本的资源,容忍这种行为。然后,因为这个bug是在Android 1.6之后被修正的,如果你需要区分Android 1.5和Android 1.6和更新版本的资源,那么你只需要提供一个1.6资源的版本后缀和一个匹配之后所有版本的资源。因此,这实际上不是一个问题。
如,如果你想对Android 1.5,1.6,2.0.1(以及之后的版本)使用不同的绘图资源,创建三个绘图路径:drawable/(1.5和更低版本),drawable-v4(1.6),以及drawable-v6(2.0.1和之后版本2.0,v5已经不再可用)。
本文来自jy02432443,是本人辛辛苦苦一个个字码出来的,转载请保留出处,并保留追究法律责任的权利 QQ78117253
第三部分:Android 应用程序接口指南---第三节:应用程序资源---第一章 资源提供的更多相关文章
- 第三部分:Android 应用程序接口指南---第五节:计算---第一章 RenderScript
第1章 RenderScript RenderScript提供一个独立于平台并在本地运行的计算引擎,用它来加速你需要大量计算能力的应用.RenderScript是一个运行与Android上计算密集型的 ...
- 第三部分:Android 应用程序接口指南---第二节:UI---第十二章 自定义组件
第12章 自定义组件 Android平台提供了一套完备的.功能强大的组件化模型用于搭建用户界面,这套组件化模型以View和 ViewGroup这两个基础布局类为基础.平台本身已预先实现了多种用于构建界 ...
- 第三部分:Android 应用程序接口指南---第二节:UI---第四章 Action Bar
第4章 Action Bar Action Bar是一个能用于确定应用程序和用户的位置,并提供给用户操作和导航模式的窗口功能.如果需要显著地展示当前用户的操作或导航,应该使用Action Bar,因为 ...
- 第三部分:Android 应用程序接口指南---第二节:UI---第九章 搜索
第9章 搜索 在android平台上搜索是一个核心的用户功能.无论内容位于设备或网络上,用户应该能够搜索任何对它们可用的数据.为了创建一个一致的用户搜索体验,Android平台提供了一个搜索框架帮助你 ...
- 第三部分:Android 应用程序接口指南---第一节:应用程序组件---第一章1-1.Fragment
第1-1章 Fragments 在Activity中的fragment代表的是一种行为或用户界面的一部分.你可以在activity中结合多个fragments创建一个多面板UI,并可以在多个activ ...
- 第三部分:Android 应用程序接口指南---第二节:UI---第一章 用户界面和布局
第1章 用户界面和布局 应用程序的用户界面就是用户能看到并可以与它交互的任何东西.Android提供多种预置的UI组件,如结构化布局对象和允许你为应用程序创建图形用户界面的UI控件.Android也会 ...
- 第三部分:Android 应用程序接口指南---第二节:UI---第二章 输入控件
第2章 输入控件 输入控件是应用程序中用户接口的一种交互式组件.Android提供了大量的可供人们在UI中使用的控件,比如按钮.文本区域.(带滑块的)进度条.复选框.缩放按钮以及切换按钮等等. 在UI ...
- 第三部分:Android 应用程序接口指南---第二节:UI---第三章 菜单
第3章 菜单 在许多不同类型的应用中,菜单通常是一种用户界面组件.为了提供给用户提供熟悉且一致的体验,你需要使用菜单API来展示用户动作和你Activity中的其他选项. 从安卓3.0系统(API l ...
- 第三部分:Android 应用程序接口指南---第二节:UI---第五章 设置(Settings)
第5章 设置(Settings) 应用程序通常包括允许用户修改应用程序的特性和行为的设置功能.例如,一些应用程序允许用户指定通知是否启用或指定多久使用云同步数据.如果你想要为你的应用程序提供设置,你应 ...
随机推荐
- python中的协程:greenlet和gevent
python中的协程:greenlet和gevent 协程是一中多任务实现方式,它不需要多个进程或线程就可以实现多任务. 1.通过yield实现协程: 代码: import time def A(): ...
- BZOJ1786 [Ahoi2008]Pair 配对 动态规划 逆序对
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1786 题意概括 给出长度为n的数列,只会出现1~k这些正整数.现在有些数写成了-1,这些-1可以变 ...
- 【Java】 剑指offer(22) 链表中倒数第k个结点
正文 本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 输入一个链表,输出该链表中倒数第k个结点.为了符合大多数人的 ...
- 021 使用join()将数组转变为字符串
1.定义用用法 join() 方法用于把数组中的所有元素放入一个字符串. 元素是通过指定的分隔符进行分隔的. 语法 arrayObject.join(separator) 返回值 返回一个字符串.该字 ...
- spring继承Rabbitmq client-----------------------待研究
一:概述 1.官网 https://spring.io/ 2.进入project 3.找到spring AMQP 二:程序 1.结构 2.pom <?xml version="1.0& ...
- POJ 2409 Let it Bead【Polya定理】(模板题)
<题目链接> 题目大意:用k种颜色对n个珠子构成的环上色,旋转.翻转后相同的只算一种,求不等价的着色方案数. 解题分析: 对于这种等价计数问题,可以用polay定理来解决,本题是一道pol ...
- python命令行解析模块--argparse
python命令行解析模块--argparse 目录 简介 详解ArgumentParser方法 详解add_argument方法 参考文档: https://www.jianshu.com/p/aa ...
- mysql字符类型大小写敏感的讨论
mysql字符类型默认是不区分大小写的,即select * from t where name='AAA'与='aaa'没区别,以下是测试的例子 (root)); (root,,,,'BbB'); ( ...
- BZOJ.2879.[NOI2012]美食节(费用流SPFA)
题目链接 /* 同"修车":对于每个厨师拆成p个点表示p个时间点,每个人向m个厨师每个时间点连边 这样边数O(nmp)+网络流 ≈O(nm*p^2)(假设SPFA线性) = GG ...
- Angular features and services overview
模块(Modules) 组件(Components) 模板(Templates) 元数据(Metadata) 数据绑定(Data binding) 指令(Directives) 服务(Services ...