程序员人生 网站导航

Android官方文档之App Resources(上)

栏目:综合技术时间:2016-07-07 13:32:22

想做出1款出色的App,仅仅编写Java代码还不够。在代码中调用资源(Resources ),如位图(bitmaps)、布局资源( layout definitions)、UI中需要展现的字符串资源(user interface strings)、动画资源(animation instructions)等,可让您的App更加出色。


本文将介绍Android中各种类型的资源、和获得资源的方式,如需访问官方原文,您可以点击这个链接:《App Resources》。


可为App提供的资源(Providing Resources)


在本小节中,将介绍可为App提供的资源类型、如何存储这些资源,和如作甚特定的装备配置替换的资源 等。


您应当将字符串、图片等资源从Java代码中剥离出来,这样方便独立地管理。另外,通过建立带有特定后缀名的资源文件夹,系统可以自动将这些文件夹中的资源设置到符合要求的装备上(如分辨率、屏幕尺寸 等)。


组合资源的类型(Grouping Resource Types)


所有的资源都寄存在res/目录下,下面是1个演示MyProject的工程结构:

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

需要注意的是,mipmap/目录下应寄存的是图标资源,而drawable/目录下寄存的是普通的图片资源,下面的表格介绍了res/目录下可以寄存的子目录名称和它们可以寄存的资源类型。

子目录名称(Directory) 资源类型(Resource Type)
animator/ 定义属性动画的XML文件
anim/ 定义补间动画的XML文件
color/ 定义色彩状态列表的XML文件
drawable/ 各种格式的位图文件(.png, .9.png, .jpg, .gif),编译为以下 Drawable 资源子类型的 XML 文件:位图文件(Bitmap files)、Nine-Patches图片、State lists、Shapes、Animation drawables、Other drawables
mipmap/ 各种分辨率的启动图标资源
layout/ 定义布局的XML文件
menu/ 定义菜单资源的XML文件。如Options Menu、Context Menu、或Sub Menu 等
raw/ 以原始格式保存的任意文件。使用InputStream打开这些资源,调用Resources.openRawResource()方法传入资源id,即:R.raw.filename.如需访问原始文件名和文件层次结构,则可以斟酌将某些资源保存在 assets/ 目录下,保存在该目录下文件的文件名不会映照到R类中,即不会生成资源ID,如需获得资源,需使用AssetManager类。
values/ 包括字符串、整型数和色彩等简单值的 XML 文件,需要使用<resources>作为根标签生命不同类型的资源,如子标签为<string>表示字符串资源、子标签<color>表示色彩资源,映照到R类分别为R.stringR.color 。为了辨别这些不同标签的文件,应在values/下建立不同的XML文件,如arrays.xml中为数组资源,colors.xml中为色彩资源,dimens.xml中为尺寸资源,strings.xml中为字符串资源,styles.xml 中为样式资源
xml/ 任何XML格式的文件,可以在程序运行时调用Resources.getXML()方法获得到。

!请注意:请不要在res/的根路径下直接寄存资源文件,否则会引发异常。


在上表中定义的子目录名称都是缺省目录名称,也就是说,定义在这些目录名称下的资源不1定是程序需要加载的“上佳”资源,而是没有最好资源时加载的“下策”资源。那末甚么是“最好”资源?Android装备千差万别,有的屏幕大、有的分辨率高:若为1个高分辨率的大屏装备加载缺省的图片资源,1定有未被利用的屏幕空间;即使是型号相同的装备,不同国家的用户可能需要设置不同的语言:若为1个设置了“中文”主题语言的装备加载“英文”的缺省资源,明显不太适合。为不同类型的装备(屏幕、语言、分辨率 等等)专门提供不同的资源,称为“最好”资源。


适配“最好”资源(Providing Alternative Resources)


几近所有的app都会为适配各式各样的装备而提供相应的资源,比如,您可能需要为不同屏幕密度的装备提供不同的drawable资源、为设置了不同系统语言的装备提供不同的string资源。在app运行时,程序会自动检测当前装备的配置信息,并为其加载适合的资源。


这里写图片描述


提供不同种类资源的方式以下:

  • res/目录下创建1个类似于<resources_name>-<config_qualifier>格式的子目录:

    • 其中<resources_name>为资源的缺省子目录名,如上1小节的表格所示;

    • <qualifier>是1个限定符,表示为满足该限定符条件的装备加载资源。以下表所示。


您可以同时使用多个<qualifier>限定符后缀,限定符之间用英文半角的破折号连接,即 “ - ”。这些限定符需要依照下面表格的顺序排列,否则该资源文件夹将被疏忽。


  • 在您创建的目录中添加的资源文件名必须和缺省目录下的文件名完全相同,以下所示:
res/ drawable/ icon.png background.png drawable-hdpi/ icon.png background.png

其中限定符hdpi表示该资源文件夹中的文件将被加载至具有高分辨率屏幕的装备上。在这些不同的drawable文件夹下,图片具有不同的分辨率,但是它们的名字相同。这样就能够使用1致的ID名将该资源援用至Java代码中。


下表罗列了您可以添加的限定符名称,再1次强调,如有多个限定符,那末需要依照下表的顺序排列。


资源类型(Configuration) 限定符举例(Qualifier Values) 描写(Description)
国家移动代码 和 网络移动代码(MCC and MNC) 举例:mcc310、mcc310-mnc004、mcc208-mnc00 MCC=The mobile country code ,国家移动代码。后面可以有选择性地跟随MNC=mobile network code,即移动网络代码。例如,mcc310代表美国的国家移动代码(MCC),而mcc310-mnc004 代表美国的Verizon运营商;而mcc208-mnc00代表法国的Orange运营商。如果装备使用的是GSM网络,那末MCC 和 MNC的代码可以在SIM卡上找到。
语言和地区(Language and region) en、fr、en-rUS、fr-rFR、fr-rCA 其中两个小写英文字母表示语言代码,具体可参照ISO 639⑴标准;由小写字母“r”开头、两个大写字母紧随其后的限定符表示地区码,地区码是1个可选限定符,您可以有选择地加入,但是地区码不能脱离语言代码而独立存在,具体可参照ISO 3166⑴-alpha⑵ 标准。当用户改变装备的系统语言时,系统加载的语言资源也应当随之改变,具体可以参照我的后续翻译,或直接点击这个链接《Handling Runtime Changes》
布局方向(Layout Direction) ldrtlldltr ldrtl表示布局的方式为从右向左(layout-direction-right-to-left),而ldltr表示从左向右(layout-direction-left-to-right),这也是默许值。这个限定符可以添加到任何资源名后,如 layout、drawable, 或 values 等。!请注意:为了添加从右至左的布局资源,需要将supportsRtl属性设置为true,并且将targetSdkVersion设置为17或以上。
最小宽度(smallestWidth) 通式情势:sw<N>dp;比如:sw320dpsw600dpsw720dp 表示屏幕的最小宽度。比如某个布局资源需要加载到最少600dp宽的装备屏幕上,那末您只需要在res/layout-sw600dp/目录下添加该布局文件便可,需要注意的是,屏幕最小宽度(smallestWidth )是1个装备的固定属性,它不会随着用户所持装备的方向而改变( The smallestWidth is a fixed screen size characteristic of the device; the device’s smallestWidth does not change when the screen’s orientation changes)。通过android:requiresSmallestWidthDp属性可以指定程序支持的最小屏幕宽度。通过smallestScreenWidthDp属性可以查询当前装备的最小宽度。
可用宽度(Available width) 通式:w<N>dp;比如:w720dpw1024dp 指定1个可用的最小宽度。这个属性会随着屏幕的横竖变化而变化。通过screenWidthDp,可以查询当前的属性值。
可用高度(Available height) 通式:h<N>dp;比如:h720dph1024dp 与可用宽度类似。使用screenHeightDp属性可以查询当前的装备的可用宽度。
屏幕大小(Screen size) smallnormallargexlarge 1般情况下使用xlarge,表示屏幕尺寸接近720dpx960dp。!请注意:如果您的限定符尺寸超过了屏幕的实际尺寸,程序将崩溃,如您的资源都放在了large文件夹下,而装备的屏幕只有normal大小。
屏幕纵横比(Screen aspect) longnotlong long:宽屏,如 WQVGA、WVGA、FWVGA;notlong:非宽屏,如 QVGA、HVGA 和 VGA
屏幕形状(Round screen) roundnotround round:圆形屏幕,如手表等装备;notround:矩形屏幕,如手机或平板.该限定符于API23引入,通过isScreenRound()可以判断装备的屏幕形状是不是为圆形。
屏幕方向(Screen orientation) portland port:屏幕为竖直方向;land:屏幕为水平方向
UI 模式(UI mode) cardesktelevisionappliancewatch car:车载系统的UI;desk:桌面系统的UI;television:电视的UI;appliance无屏幕的装备;watch:手表装备。
夜间模式(Night mode) nightnotnight night:晚间;notnight:白天。
屏幕像素密度(Screen pixel density (dpi)) ldpimdpihdpixhdpixxhdpixxxhdpinodpitvdpianydpi 主流:xhdpi:接近320dpi;xxhdpi:接近480dpi;xxxhdpi:只针对启动图标,接近640dpi。
触屏类型(Touchscreen type) notouchfinger notouch:装备无触屏;finger:装备包括触摸屏。
键盘可用性(Keyboard availability) keysexposedkeyshiddenkeyssoft keysexposed:装备具有可用的键盘;keyshidden:装备具有可用的硬键盘,但它处于隐藏状态,且装备没有启用软键盘;keyssoft:装备已启用软键盘(不管是不是可见)。
主要文本输入法(Primary text input method) nokeysqwerty12key nokeys:装备没有用于文本输入的硬按键;qwerty:装备具有标准硬键盘(不管是不是对用户可见);12key:装备具有 12 键硬键盘(不管是不是对用户可见)。
导航键可用性(Navigation key availability) navexposednavhidden navexposed:导航键可供用户使用;navhidden:导航键不可用(例如,位于密封盖子后面)。`
主要非触摸导航方法(Primary non-touch navigation method) nonavdpadtrackballwheel nonav:除使用触摸屏之外,装备没有其他导航设施;dpad:装备具有用于导航的方向键;trackball:装备具有用于导航的轨迹球;wheel:装备具有用于导航的方向盘(不常见)。
平台版本(API 级别)(Platform Version (API level)) v3v4v7 装备支持的 API 级别。例如,v1 对应于 API 级别 1(带有 Android 1.0 或更高版本系统的装备),v4 对应于 API 级别 4(带有 Android 1.6 或更高版本系统的装备)。

!请注意:其实不是所有的限定符都是在API 1 中加入的,所以,为了避免某些高版本的限定符不被加载(装备版本较低),请务必为所有资源设置默许的资源文件夹。


限定符的命名规则(Qualifier name rules)


  • 您可以同时使用多个限定符,用破折号连接,比如:drawable-en-rUS-land,这表示当装备处于横屏状态且系统语言为英文时加载该文件夹下的文件。

  • 多个限定符必须依照上表的顺序排列,比如:

    • drawable-hdpi-port/,毛病;

    • drawable-port-hdpi/,正确。


  • 每种资源文件夹不可被嵌套,比如:res/drawable/drawable-en/

  • 文件夹的名称是大小写不敏感的(case-insensitive)。在处理之前,资源编译器会将目录名称转换为小写,以免不辨别大小写的文件系统出现问题。 名称中使用的任何大写字母只是为了便于认读。

  • 对每种限定符类型,仅支持1个值。例如,若要对西班牙语和法语使用相同的 Drawable 文件,则您肯定不能具有名为 drawable-rES-rFR/ 的目录,而是需要两个包括相应文件的资源目录,如 drawable-rES/drawable-rFR/。但是,实际上您无需将相同的文件都复制到这两个位置。相反,您可以创建指向资源的别名。


创建别名资源(Creating alias resources)


假定您有1个利用图标 icon.png,并且需要不同区域设置的独特版本。 但是,加拿大英语和加拿大法语这两种区域设置需要使用同1版本。 您可能会认为需要将相同的图象复制到加拿大英语和加拿大法语对应的资源目录中,但事实并不是如此。 相反,您可以将用于2者的图象另存为 icon_ca.png(除 icon.png 之外的任何名称),并将其放入默许 res/drawable/ 目录中。然后,在 res/drawable-en-rCA/res/drawable-fr-rCA/ 中创建 icon.xml 文件,使用 <bitmap>标签; 元素援用 icon_ca.png资源。这样,您只需存储 PNG 文件的1个版本和两个指向该版本的小型 XML 文件。(XML 文件示例以下。)


Drawable资源(Drawable)


<?xml version="1.0" encoding="utf⑻"?> <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资源(Layout)


要创建指向现有布局的别名,请使用包装在 <merge>标签中的 <include>元素。例如:

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

如果将此文件另存为 main.xml,则会编译到可作为 R.layout.main 援用的资源中,但实际上它是 R.layout.main_ltr 资源的别名.


Strings资源和其他简单数值资源(Strings and other simple values)


要创建指向现有字符串的别名,只需将所需字符串的资源 ID 用作新字符串的值便可。例如:

<?xml version="1.0" encoding="utf⑻"?> <resources> <string name="hello">Hello</string> <string name="hi">@string/hello</string> </resources>

R.string.hi 资源现在是 R.string.hello 的别名。


其他简单数值资源的别名使用与Strings类似,例如:

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

为装备匹配最好资源(Providing the Best Device Compatibility with Resources)


请务必提供默许资源。比如,如果利用支持多种语言,请始终包括不带语言和区域限定符的 values/ 目录(用于保存字符串)。相反,如果您将所有字符串放入带有语言和区域限定符的目录中,则在语言设置不支持您的字符串的装备上运行利用时,利用将会崩溃。
一样,如果您根据屏幕方向提供不同的布局资源,则应选择1个方向作为默许方向。 例如,不要在 layout-land/layout-port/ 中分别提供横向和纵向的布局资源,而是保存其中之1作为默许设置,例如:layout/ 用于横向,layout-port/ 用于纵向。


Android装备如何匹配最好资源(How Android Finds the Best-matching Resource)


当您要求要为其提供备用资源的资源时,Android 会根据当前的装备配置选择要在运行时使用的备用资源。假定Drawable 目录分别包括相同图象的不同版本:

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

装备终究加载的是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/

2、 选择上表中(下1个)优先级最高的限定符。(先从 MCC 开始,然后下移。)

3、 是不是有资源目录包括此限定符?

  • 若无,请返回到第 2 步,看看下1个限定符。(在该示例中,除非到达语言限定符,否则答案始终为“否”。)

  • 若有,请继续履行第 4 步。

4、淘汰不含此限定符的资源目录。在该示例中,系统会淘汰所有不含语言限定符的目录:

drawable/ //淘汰 drawable-en/ drawable-en-port/ drawable-en-notouch-12key/ drawable-port-ldpi/ //淘汰 drawable-port-notouch-12key/ //淘汰

5、返回并重复第 2 步、第 3 步和第 4 步,直到只剩下1个目录为止。在此示例中,屏幕方向是下1个判断是不是匹配的限定符。因此,未指定屏幕方向的资源被淘汰:

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

流程图以下所示:
这里写图片描述


!请注意:注:限定符的优先顺序(上表 中)比与装备完全匹配的限定符数量更加重要。例如,在上面的第 4 步中,列表剩下的最后选项包括3个与装备完全匹配的限定符(方向、触摸屏类型和输入法),而 drawable-en 只有1个匹配参数(语言)。但是,语言的优先顺序高于其他两个限定符,因此 drawable-port-notouch⑴2key 被淘汰。


访问资源(Accessing Resources)


您在利用中提供资源后,可通过援用其资源 ID 来获得该资源,所有的资源ID均被定义在R类 中。
资源 ID 由以下部份组成:

  • 资源类型:每一个资源都被分到1个“类型”组中,例如 stringdrawablelayout
  • 资源名称:它是不包括扩大名的文件名。

访问资源的方法有两种:

  • 在代码中:使用来自 R 类的某个子类的静态整型数,例如:

    • R.string.hello

    string 是资源类型,hello 是资源名称。

  • 在 XML 中:使用一样与您 R 类中定义的资源 ID 对应的特殊 XML 语法,如:

    • @string/hello

    string 是资源类型,hello 是资源名称。


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


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

举例(Use cases)


// Load a background for the current screen from a drawable resource getWindow().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 ID getWindow().setTitle(getResources().getText(R.string.main_title)); // Load a custom layout for the current screen setContentView(R.layout.main_screen); // Set a slide in animation by getting an Animation from the Resources object mFlipper.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.hyperspace_in)); // Set the text on a TextView object using a resource ID TextView msgTextView = (TextView) findViewById(R.id.msg); msgTextView.setText(R.string.hello_message);

在 XML 中访问资源(Accessing Resources from XML)


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

举例(Use cases)

如果您具有以下资源文件,其中包括1个色彩资源和1个字符串资源:

<?xml version="1.0" encoding="utf⑻"?> <resources> <color name="opaque_red">#f00</color> <string name="hello">Hello!</string> </resources>

您可以在以下布局文件中使用这些资源来设置文本色彩和文本字符串:

<?xml version="1.0" encoding="utf⑻"?> <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⑻"?> <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" />

援用样式属性(Referencing style attributes)


要援用样式属性,名称语法几近与普通资源格式完全相同,只不过将 at 符号 (@) 改成问号 (?),资源类型部份为可选项。 例如:

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

例如,您可以通过以下代码援用1个属性,将文本色彩设置为与系统风格主题的“主要”文本色彩匹配:

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

在以上代码中,android:textColor 属性表示当前风格主题中某个样式属性的名称。


访问平台资源(Referencing style attributes)


Android 包括许多标准资源,例如样式、风格主题和布局。要访问这些资源,请通过 android 包名称限定您的资源援用。例如,您可以将 Android 提供的布局资源用于 ListAdapter 中的列表项:

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

simple_list_item_1 是平台为 ListView 中的项目定义的布局资源。您可使用它,而没必要自行创建列表项布局。


处理运行时变更(Handling Runtime Changes)


有些装备配置可能会在运行时产生变化(例如屏幕方向、键盘可用性及语言)。 产生这类变化时,Android 会重启正在运行的 Activity(前后调用 onDestroy() 和 onCreate())。重启行动旨在通过利用与新装备配置匹配的备用资源自动重新加载您的利用,来帮助它适应新配置。


要妥善处理重启行动,Activity 必须通过常规的Activity 生命周期恢复其之前的状态,在 Activity 生命周期中,Android 会在烧毁 Activity 之前调用 onSaveInstanceState(),以便您保存有关利用状态的数据。 然后,您可以在 onCreate() 或 onRestoreInstanceState() 期间恢复 Activity 状态。


但是,重启利用并恢复大量数据不但本钱高昂,而且给用户留下糟的使用体验。 在这类情况下,您有两个其他选择:


  • 在配置变更期间保存对象:

    • 允许 Activity 在配置变更时重启,但是要将有状态对象传递给 Activity 的新实例。
  • 自行处理配置变更:

    • 禁止系统在某些配置变更期间重启 Activity,但要在配置确切产生变化时接收回调,这样,您就可以够根据需要手动更新 Activity。

在配置变更期间保存对象(Retaining an Object During a Configuration Change)

如果重启 Activity 需要恢复大量数据、重新建立网络连接或履行其他密集操作,那末因配置变更而引发的完全重启可能会给用户留下利用运行缓慢的体验。 另外,依托系统通过 onSaveInstanceState() 回调为您保存的 Bundle,可能没法完全恢复 Activity 状态,由于它 并不是设计用于携带大型对象(例如位图),而且其中的数据必须先序列化,再进行反序列化, 这可能会消耗大量内存并使得配置变更速度缓慢。
在这类情况下,如果 Activity 因配置变更而重启,则可通过保存 Fragment 来减轻重新初始化 Activity 的负担。此Fragment可能包括对您要保存的有状态对象的援用。

当 Android 系统因配置变更而关闭 Activity 时,不会烧毁您已标记为要保存的 Activity 的Fragment。您可以将此类Fragment添加到 Activity 以保存有状态的对象。


要在运行时配置变更期间将有状态的对象保存在Fragment中,请履行以下操作:


1、继承 Fragment 类并声明对有状态对象的援用。
2、在创建Fragment后调用 setRetainInstance(boolean)
3、将Fragment添加到 Activity。
4、重启 Activity 后,使用 FragmentManager 检索Fragment。


public class RetainedFragment extends Fragment { // data object we want to retain private MyDataObject data; // this method is only called once for this fragment @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // retain this fragment setRetainInstance(true); } public void setData(MyDataObject data) { this.data = data; } public MyDataObject getData() { return data; } }

!请注意:虽然您可以存储任何对象,但是切勿传递与 Activity 绑定的对象,例如,Drawable、Adapter、View 或其他任何与 Context 关联的对象。否则,它将泄漏原始 Activity 实例的所有视图和资源。 (泄漏资源意味着利用将继续持有这些资源,但是没法对其进行垃圾回收,因此可能会丢失大量内存。)


然后,使用 FragmentManager 将Fragment添加到 Activity。在运行时配置变更期间再次启动 Activity 时,您可以取得Fragment中的数据对象。 例如,按以下所示定义 Activity:

public class MyActivity extends Activity { private RetainedFragment dataFragment; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // find the retained fragment on activity restarts FragmentManager fm = getFragmentManager(); dataFragment = (DataFragment) fm.findFragmentByTag(“data”); // create the fragment and data the first time if (dataFragment == null) { // add the fragment dataFragment = new DataFragment(); fm.beginTransaction().add(dataFragment, “data”).commit(); // load the data from the web dataFragment.setData(loadMyData()); } // the data is available in dataFragment.getData() ... } @Override public void onDestroy() { super.onDestroy(); // store the data in the fragment dataFragment.setData(collectMyLoadedData()); } }

自行处理配置变更(Handling the Configuration Change Yourself)


如果利用在特定配置变更期间无需更新资源,并且因性能限制您需要尽可能避免重启,则可声明 Activity 将自行处理配置变更,这样可以禁止系统重启 Activity。
!请注意:自行处理配置变更可能致使备用资源的使用更加困难,由于系统不会为您自动利用这些资源。 只能在您必须避免Activity因配置变更而重启这1万般无奈的情况下,才斟酌采取自行处理配置变更这类方法,而且对大多数利用其实不建议使用此方法。


要声明由 Activity 处理配置变更,请在清单文件中编辑相应的 <activity>标签,以包括 android:configChanges 属性和代表要处理的配置的值。android:configChanges属性的文档中列出了该属性的可能值(最经常使用的值包括 “orientation” 和 “keyboardHidden“,分别用于避免因屏幕方向和可用键盘改变而致使重启)。您可以在该属性中声明多个配置值,方法是用 ” | ” 字符分隔这些配置值:

<activity android:name=".MyActivity" android:configChanges="orientation|keyboardHidden" android:label="@string/app_name">

orientation 或 keyboardHidden配置产生变化时,MyActivity 不会重启。相反,MyActivity 会收到对 onConfigurationChanged()的调用。向此方法传递 Configuration 对象指定新装备配置。您可以通过读取 Configuration 中的字段,肯定新配置,然后通过更新界面中使用的资源进行适当的更改。调用此方法时,ActivityResources 对象会相应地进行更新,以根据新配置返回资源,这样,您就可以够在系统不重启 Activity 的情况下轻松重置 UI 的元素。

!请注意:从 Android 3.2(API 级别 13)开始,当装备在纵向和横向之间切换时,“屏幕尺寸”也会产生变化。因此,在开发针对 API 级别 13 或更高版本系统的利用时,若要避免由于装备方向改变而致使运行时重启,则除 “orientation” 值之外,您还必须添加 “screenSize” 值。即,您必须声明 android:configChanges="orientation|screenSize"


@Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // Checks the orientation of the screen if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show(); } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){ Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show(); } }

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐