想做出1款出色的App,僅僅編寫Java代碼還不夠。在代碼中調用資源(Resources ),如位圖(bitmaps)、布局資源( layout definitions)、UI中需要展現的字符串資源(user interface strings)、動畫資源(animation instructions)等,可讓您的App更加出色。
本文將介紹Android中各種類型的資源、和獲得資源的方式,如需訪問官方原文,您可以點擊這個鏈接:《App Resources》。
在本小節中,將介紹可為App提供的資源類型、如何存儲這些資源,和如作甚特定的裝備配置替換的資源 等。
您應當將字符串、圖片等資源從Java代碼中剝離出來,這樣方便獨立地管理。另外,通過建立帶有特定后綴名的資源文件夾,系統可以自動將這些文件夾中的資源設置到符合要求的裝備上(如分辨率、屏幕尺寸 等)。
所有的資源都寄存在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.string 、R.color 。為了辨別這些不同標簽的文件,應在values/ 下建立不同的XML文件,如arrays.xml 中為數組資源,colors.xml 中為色彩資源,dimens.xml 中為尺寸資源,strings.xml 中為字符串資源,styles.xml 中為樣式資源 |
xml/ |
任何XML格式的文件,可以在程序運行時調用Resources.getXML() 方法獲得到。 |
!請注意:請不要在res/
的根路徑下直接寄存資源文件,否則會引發異常。
在上表中定義的子目錄名稱都是缺省目錄名稱,也就是說,定義在這些目錄名稱下的資源不1定是程序需要加載的“上佳”資源,而是沒有最好資源時加載的“下策”資源。那末甚么是“最好”資源?Android裝備千差萬別,有的屏幕大、有的分辨率高:若為1個高分辨率的大屏裝備加載缺省的圖片資源,1定有未被利用的屏幕空間;即使是型號相同的裝備,不同國家的用戶可能需要設置不同的語言:若為1個設置了“中文”主題語言的裝備加載“英文”的缺省資源,明顯不太適合。為不同類型的裝備(屏幕、語言、分辨率 等等)專門提供不同的資源,稱為“最好”資源。
幾近所有的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) | ldrtl 、ldltr |
ldrtl 表示布局的方式為從右向左(layout-direction-right-to-left),而ldltr 表示從左向右(layout-direction-left-to-right),這也是默許值。這個限定符可以添加到任何資源名后,如 layout、drawable, 或 values 等。!請注意:為了添加從右至左的布局資源,需要將supportsRtl 屬性設置為true,并且將targetSdkVersion 設置為17或以上。 |
最小寬度(smallestWidth) | 通式情勢:sw<N>dp ;比如:sw320dp 、sw600dp 、sw720dp 等 |
表示屏幕的最小寬度。比如某個布局資源需要加載到最少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 ;比如:w720dp 、w1024dp 等 |
指定1個可用的最小寬度。這個屬性會隨著屏幕的橫豎變化而變化。通過screenWidthDp ,可以查詢當前的屬性值。 |
可用高度(Available height) | 通式:h<N>dp ;比如:h720dp 、h1024dp 等 |
與可用寬度類似。使用screenHeightDp 屬性可以查詢當前的裝備的可用寬度。 |
屏幕大?。⊿creen size) | small 、normal 、large 、xlarge |
1般情況下使用xlarge ,表示屏幕尺寸接近720dpx960dp。!請注意:如果您的限定符尺寸超過了屏幕的實際尺寸,程序將崩潰,如您的資源都放在了large 文件夾下,而裝備的屏幕只有normal 大小。 |
屏幕縱橫比(Screen aspect) | long 、notlong |
long :寬屏,如 WQVGA、WVGA、FWVGA;notlong :非寬屏,如 QVGA、HVGA 和 VGA |
屏幕形狀(Round screen) | round 、notround |
round :圓形屏幕,如手表等裝備;notround :矩形屏幕,如手機或平板.該限定符于API23引入,通過isScreenRound() 可以判斷裝備的屏幕形狀是不是為圓形。 |
屏幕方向(Screen orientation) | port 、land |
port :屏幕為豎直方向;land :屏幕為水平方向 |
UI 模式(UI mode) | car 、desk 、television 、appliance 、watch |
car :車載系統的UI;desk :桌面系統的UI;television :電視的UI;appliance 無屏幕的裝備;watch :手表裝備。 |
夜間模式(Night mode) | night 、notnight |
night :晚間;notnight :白天。 |
屏幕像素密度(Screen pixel density (dpi)) | ldpi 、mdpi 、hdpi 、xhdpi 、xxhdpi 、xxxhdpi 、nodpi 、tvdpi 、anydpi |
主流:xhdpi :接近320dpi;xxhdpi :接近480dpi;xxxhdpi :只針對啟動圖標,接近640dpi。 |
觸屏類型(Touchscreen type) | notouch 、finger |
notouch :裝備無觸屏;finger :裝備包括觸摸屏。 |
鍵盤可用性(Keyboard availability) | keysexposed 、keyshidden 、keyssoft |
keysexposed :裝備具有可用的鍵盤;keyshidden :裝備具有可用的硬鍵盤,但它處于隱藏狀態,且裝備沒有啟用軟鍵盤;keyssoft :裝備已啟用軟鍵盤(不管是不是可見)。 |
主要文本輸入法(Primary text input method) | nokeys 、qwerty 、12key |
nokeys :裝備沒有用于文本輸入的硬按鍵;qwerty :裝備具有標準硬鍵盤(不管是不是對用戶可見);12key :裝備具有 12 鍵硬鍵盤(不管是不是對用戶可見)。 |
導航鍵可用性(Navigation key availability) | navexposed 、navhidden |
navexposed :導航鍵可供用戶使用;navhidden:導航鍵不可用(例如,位于密封蓋子后面)。` |
主要非觸摸導航方法(Primary non-touch navigation method) | nonav 、dpad 、trackball 、wheel |
nonav :除使用觸摸屏之外,裝備沒有其他導航設施;dpad :裝備具有用于導航的方向鍵;trackball :裝備具有用于導航的軌跡球;wheel :裝備具有用于導航的方向盤(不常見)。 |
平臺版本(API 級別)(Platform Version (API level)) | v3 、v4 、v7 等 |
裝備支持的 API 級別。例如,v1 對應于 API 級別 1(帶有 Android 1.0 或更高版本系統的裝備),v4 對應于 API 級別 4(帶有 Android 1.6 或更高版本系統的裝備)。 |
!請注意:其實不是所有的限定符都是在API 1 中加入的,所以,為了避免某些高版本的限定符不被加載(裝備版本較低),請務必為所有資源設置默許的資源文件夾。
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/
。但是,實際上您無需將相同的文件都復制到這兩個位置。相反,您可以創建指向資源的別名。
假定您有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 文件示例以下。)
<?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/
中)的別名。
要創建指向現有布局的別名,請使用包裝在 <merge>
標簽中的 <include>
元素。例如:
<?xml version="1.0" encoding="utf⑻"?>
<merge>
<include layout="@layout/main_ltr"/>
</merge>
如果將此文件另存為 main.xml
,則會編譯到可作為 R.layout.main
援用的資源中,但實際上它是 R.layout.main_ltr
資源的別名.
要創建指向現有字符串的別名,只需將所需字符串的資源 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>
請務必提供默許資源。比如,如果利用支持多種語言,請始終包括不帶語言和區域限定符的 values/
目錄(用于保存字符串)。相反,如果您將所有字符串放入帶有語言和區域限定符的目錄中,則在語言設置不支持您的字符串的裝備上運行利用時,利用將會崩潰。
一樣,如果您根據屏幕方向提供不同的布局資源,則應選擇1個方向作為默許方向。 例如,不要在 layout-land/
和 layout-port/
中分別提供橫向和縱向的布局資源,而是保存其中之1作為默許設置,例如:layout/
用于橫向,layout-port/
用于縱向。
當您要求要為其提供備用資源的資源時,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
被淘汰。
您在利用中提供資源后,可通過援用其資源 ID 來獲得該資源,所有的資源ID均被定義在R類 中。
資源 ID 由以下部份組成:
string
、drawable
和 layout
。訪問資源的方法有兩種:
在代碼中:使用來自 R 類的某個子類的靜態整型數,例如:
R.string.hello
string 是資源類型,hello 是資源名稱。
在 XML 中:使用一樣與您 R 類中定義的資源 ID 對應的特殊 XML 語法,如:
@string/hello
string 是資源類型,hello 是資源名稱。
ImageView imageView = (ImageView) findViewById(R.id.myimageview);
imageView.setImageResource(R.drawable.myimage);
// 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);
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/submit" />
如果您具有以下資源文件,其中包括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" />
要援用樣式屬性,名稱語法幾近與普通資源格式完全相同,只不過將 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
屬性表示當前風格主題中某個樣式屬性的名稱。
Android 包括許多標準資源,例如樣式、風格主題和布局。要訪問這些資源,請通過 android 包名稱限定您的資源援用。例如,您可以將 Android 提供的布局資源用于 ListAdapter
中的列表項:
setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myarray));
simple_list_item_1
是平臺為 ListView
中的項目定義的布局資源。您可使用它,而沒必要自行創建列表項布局。
有些裝備配置可能會在運行時產生變化(例如屏幕方向、鍵盤可用性及語言)。 產生這類變化時,Android 會重啟正在運行的 Activity(前后調用 onDestroy() 和 onCreate())。重啟行動旨在通過利用與新裝備配置匹配的備用資源自動重新加載您的利用,來幫助它適應新配置。
要妥善處理重啟行動,Activity 必須通過常規的Activity 生命周期恢復其之前的狀態,在 Activity 生命周期中,Android 會在燒毀 Activity 之前調用 onSaveInstanceState(),以便您保存有關利用狀態的數據。 然后,您可以在 onCreate() 或 onRestoreInstanceState() 期間恢復 Activity 狀態。
但是,重啟利用并恢復大量數據不但本錢高昂,而且給用戶留下糟的使用體驗。 在這類情況下,您有兩個其他選擇:
在配置變更期間保存對象:
自行處理配置變更:
如果重啟 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());
}
}
如果利用在特定配置變更期間無需更新資源,并且因性能限制您需要盡可能避免重啟,則可聲明 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
中的字段,肯定新配置,然后通過更新界面中使用的資源進行適當的更改。調用此方法時,Activity
的 Resources
對象會相應地進行更新,以根據新配置返回資源,這樣,您就可以夠在系統不重啟 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();
}
}
上一篇 微信支付公的眾號支付和掃碼支付