您應該始終外部化應用資源,例如圖像和代碼中的字符串,這樣有利於您單獨維護這些資源。 此外,您還應該爲特定設備配置提供備用資源,方法是將它們分組到專門命名的資源目錄中。 在運行時,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.res/ 目錄內支持的資源目錄
目錄 |
資源類型 |
animator/ |
用於定義屬性動畫的 XML 文件。 |
anim/ |
定義漸變動畫的 XML 文件。(屬性動畫也可以保存在此目錄中,但是爲了區分這兩種類型,屬性動畫首選 animator/ 目錄。) |
color/ |
用於定義顏色狀態列表的 XML 文件。請參閱顏色狀態列表資源 |
drawable/ |
位圖文件(.png、.9.png、.jpg、.gif)或編譯爲以下 Drawable 資源子類型的 XML 文件: • 位圖文件 • 九宮格(可調整大小的位圖) • 狀態列表 • 形狀 • 動畫 Drawable • 其他 Drawable 請參閱 Drawable 資源。 |
mipmap/ |
適用於不同啓動器圖標密度的 Drawable 文件。如需瞭解有關使用 mipmap/ 文件夾管理啓動器圖標的詳細信息,請參閱管理項目概覽。 |
layout/ |
用於定義用戶界面佈局的 XML 文件。 請參閱佈局資源。 |
menu/ |
用於定義應用菜單(如選項菜單、上下文菜單或子菜單)的 XML 文件。請參閱菜單資源。 |
raw/ |
要以原始形式保存的任意文件。要使用原始 InputStream 打開這些資源,請使用資源 ID(即 R.raw.<em>filename</em>)調用 Resources.openRawResource()。 但是,如需訪問原始文件名和文件層次結構,則可以考慮將某些資源保存在 assets/ 目錄下(而不是 res/raw/)。assets/ 中的文件沒有資源 ID,因此您只能使用 AssetManager 讀取這些文件。 |
values/ |
包含字符串、整型數和顏色等簡單值的 XML 文件。 其他 res/ 子目錄中的 XML 資源文件是根據 XML 文件名定義單個資源,而目錄中的 values/ 文件可描述多個資源。對於此目錄中的文件,<resources> 元素的每個子元素均定義一個資源。例如,<string> 元素創建 R.string 資源,<color> 元素創建 R.color 資源。 由於每個資源均用其自己的 XML 元素定義,因此您可以根據自己的需要命名文件,並將不同的資源類型放在一個文件中。但是,爲了清晰起見,您可能需要將獨特的資源類型放在不同的文件中。 例如,對於可在此目錄中創建的資源,下面給出了相應的文件名約定: • arrays.xml,用於資源數組(類型化數組)。 • colors.xml:顏色值。 • dimens.xml:尺寸值。 • strings.xml:字符串值。 • styles.xml:樣式。 |
xml/ |
可以在運行時通過調用 Resources.getXML() 讀取的任意 XML 文件。各種 XML 配置文件(如可搜索配置)都必須保存在此處。 |
注意:切勿將資源文件直接保存在 res/ 目錄內,這會導致出現編譯錯誤。
保存在表 1 中定義的子目錄下的資源是“默認”資源。即,這些資源定義應用的默認設計和內容。但是,採用 Android 技術的不同設備類型可能需要不同類型的資源。例如,如果設備的屏幕尺寸大於標準屏幕,則應提供不同的佈局資源,以充分利用額外的屏幕空間。 或者,如果設備的語言設置不同,則應提供不同的字符串資源,以轉換用戶界面中的文本。 要爲不同的設備配置提供這些不同資源,除了默認資源以外,您還需要提供備用資源。
提供備用資源
幾乎每個應用都應提供備用資源以支持特定的設備配置。 例如,對於不同的屏幕密度和語言,您應分別包括備用 Drawable 資源和備用字符串資源。 在運行時,Android 會檢測當前設備配置併爲應用加載合適的資源。
爲一組資源指定特定於配置的備用資源:
在 res/ 中創建一個以 <resources_name>-<config_qualifier> 形式命名的新目錄。
<resources_name> 是相應默認資源的目錄名稱(如表 1 中所定義)。
<qualifier> 是指定要使用這些資源的各個配置的名稱(如表 2 中所定義)。
您可以追加多個 <qualifier>。以短劃線將其分隔。
注意:追加多個限定符時,必須按照表 2 中列出的相同順序放置它們。如果限定符的順序錯誤,則該資源將被忽略。
將相應的備用資源保存在此新目錄下。這些資源文件的名稱必須與默認資源文件完全一樣。
例如,以下是一些默認資源和備用資源:
res/
drawable/
icon.png
background.png
drawable-hdpi/
icon.png
background.png
hdpi 限定符表示該目錄中的資源適用於屏幕密度較高的設備。其中每個 Drawable 目錄中的圖像已針對特定的屏幕密度調整大小,但是文件名完全相同。 這樣一來,用於引用 icon.png 或 background.png 圖像的資源 ID 始終相同,但是 Android 會通過將設備配置信息與資源目錄名稱中的限定符進行比較,選擇最符合當前設備的各個資源版本。
Android 支持若干配置限定符,您可以通過使用短劃線分隔每個限定符,向一個目錄名稱添加多個限定符。表 2 按優先順序列出了有效的配置限定符;如果對資源目錄使用多個限定符,則必須按照表中列出的順序將它們添加到目錄名稱。
表 2. 配置限定符名稱。
配置 | 限定符值 | 描述 |
---|---|---|
MCC 和 MNC |
示例:mcc310 mcc310-mnc004 mcc208-mnc00 等等 |
移動國家代碼 (MCC),(可選)後跟設備 SIM 卡中的移動網絡代碼 (MNC)。例如, 如果設備使用無線電連接(GSM 手機),則 MCC 和 MNC 值來自 SIM 卡。 也可以單獨使用 MCC(例如,將國家/地區特定的合法資源包括在應用中)。如果只需根據語言指定,則改用“語言和區域”限定符(稍後進行介紹)。 如果決定使用 MCC 和 MNC 限定符,請謹慎執行此操作並測試限定符是否按預期工作。 |
語言和區域 |
示例:en fr en-rUS fr-rFR fr-rCA 等等 |
語言通過由兩個字母組成的 ISO 639-1 語言代碼定義,(可選)後跟兩個字母組成的 ISO
3166-1-alpha-2 區域碼(前帶小寫字母“ 這些代碼不區分大小寫; 如果用戶更改系統設置中的語言,它有可能在應用生命週期中發生改變。 如需瞭解這會在運行期間給應用帶來哪些影響,請參閱處理運行時變更。 有關針對其他語言本地化應用的完整指南,請參閱本地化。 另請參閱 |
佈局方向 |
ldrtl ldltr |
應用的佈局方向。 它適用於佈局、圖片或值等任何資源。 例如,若要針對阿拉伯語提供某種特定佈局,並針對任何其他“從右到左”語言(如波斯語或希伯來語)提供某種通用佈局,則可編碼如下: res/ layout/ main.xml (Default layout) layout-ar/ main.xml (Specific layout for Arabic) layout-ldrtl/ main.xml (Any "right-to-left" language, except for Arabic, because the "ar" language qualifier has a higher precedence.)
注:要爲應用啓用從右到左的佈局功能,必須將 此項爲API 級別 17 中新增配置。 |
smallestWidth |
sw<N>dp 示例: sw320dp sw600dp sw720dp 等等 |
屏幕的基本尺寸,由可用屏幕區域的最小尺寸指定。 具體來說,設備的 smallestWidth 是屏幕可用高度和寬度的最小尺寸(您也可以將其視爲屏幕的“最小可能寬度”)。無論屏幕的當前方向如何,您均可使用此限定符確保應用 UI 的可用寬度至少爲 例如,如果佈局要求屏幕區域的最小尺寸始終至少爲 600dp,則可使用此限定符創建佈局資源 設備的 smallestWidth 將屏幕裝飾元素和系統 UI 考慮在內。例如,如果設備的屏幕上有一些永久性 UI 元素佔據沿 smallestWidth 軸的空間,則系統會聲明 smallestWidth 小於實際屏幕尺寸,因爲這些屏幕像素不適用於您的 UI。因此,使用的值應該是佈局所需要的實際最小尺寸(通常,無論屏幕的當前方向如何,此值都是佈局支持的“最小寬度”)。 以下是一些可用於普通屏幕尺寸的值:
應用爲多個資源目錄提供不同的 smallestWidth 限定符值時,系統會使用最接近(但未超出)設備 smallestWidth 的值。 此項爲 API 級別 13 中新增配置。 另請參閱 如需瞭解有關設計不同屏幕和使用此限定符的詳細信息,請參閱支持多個屏幕開發者指南。 |
可用寬度 |
w<N>dp 示例: w720dp w1024dp 等等 |
指定資源應該使用的最小可用屏幕寬度,以 應用爲多個資源目錄提供不同的此配置值時,系統會使用最接近(但未超出)設備當前屏幕寬度的值。 此處的值考慮到了屏幕裝飾元素,因此如果設備顯示屏的左邊緣或右邊緣上有一些永久性 UI 元素,考慮到這些 UI 元素,它會使用小於實際屏幕尺寸的寬度值,這樣會減少應用的可用空間。 此項爲 API 級別 13 中新增配置。 另請參閱 如需瞭解有關設計不同屏幕和使用此限定符的詳細信息,請參閱支持多個屏幕開發者指南。 |
可用高度 |
h<N>dp 示例: h720dp h1024dp 等等 |
指定資源應該使用的最小可用屏幕高度,以“dp”爲單位,由 應用爲多個資源目錄提供不同的此配置值時,系統會使用最接近(但未超出)設備當前屏幕高度的值。 此處的值考慮到了屏幕裝飾元素,因此如果設備顯示屏的上邊緣或下邊緣有一些永久性 UI 元素,考慮到這些 UI 元素,同時爲減少應用的可用空間,它會使用小於實際屏幕尺寸的高度值。 非固定的屏幕裝飾元素(例如,全屏時可隱藏的手機狀態欄)並不在考慮範圍內,標題欄或操作欄等窗口裝飾也不在考慮範圍內,因此應用必須準備好處理稍小於其所指定值的空間。 此項爲 API 級別 13 中新增配置。 另請參閱 如需瞭解有關設計不同屏幕和使用此限定符的詳細信息,請參閱支持多個屏幕開發者指南。 |
屏幕尺寸 |
small normal large xlarge |
注:使用尺寸限定符並不表示資源僅適用於該尺寸的屏幕。 如果沒有爲備用資源提供最符合當前設備配置的限定符,則系統可能使用其中最匹配的資源。
注意:如果所有資源均使用大於當前屏幕的尺寸限定符,則系統不會使用這些資源,並且應用在運行時將會崩潰(例如,如果所有佈局資源均用 此項爲 API 級別 4 中新增配置。 如需瞭解詳細信息,請參閱支持多個屏幕。 另請參閱 |
屏幕縱橫比 |
long notlong |
此項爲 API 級別 4 中新增配置。 它完全基於屏幕的縱橫比(寬屏較寬),而與屏幕方向無關。 另請參閱 |
屏幕方向 |
port land |
如果用戶旋轉屏幕,它有可能在應用生命週期中發生改變。 如需瞭解這會在運行期間給應用帶來哪些影響,請參閱處理運行時變更。 另請參閱 |
UI 模式 |
car desk television appliance watch |
此項爲 API 級別 8 中新增配置,API 13 中新增電視配置,API 20 中新增手錶配置。 如需瞭解應用在設備插入手機座或從中移除時的響應方式,請閱讀確定並監控插接狀態和類型。 如果用戶將設備放入手機座中,它有可能在應用生命週期中發生改變。 可以使用 |
夜間模式 |
night notnight |
此項爲 API 級別 8 中新增配置。 如果夜間模式停留在自動模式(默認),它有可能在應用生命週期中發生改變。在這種情況下,該模式會根據當天的時間進行調整。 可以使用 |
屏幕像素密度 (dpi) |
ldpi mdpi hdpi xhdpi xxhdpi xxxhdpi nodpi tvdpi |
六個主要密度之間的縮放比爲 3:4:6:8:12:16(忽略 tvdpi 密度)。因此,9x9 (ldpi) 位圖相當於 12x12 (mdpi)、18x18 (hdpi)、24x24 (xhdpi) 位圖,依此類推。 如果您認爲圖像資源在電視或其他某些設備上呈現的效果不夠好,而想嘗試使用 tvdpi 資源,則縮放比例爲 1.33*mdpi。例如,mdpi 屏幕的 100px x 100px 圖像應該相當於 tvdpi 的133px x 133px。 注:使用密度限定符並不表示資源僅適用於該密度的屏幕。 如果沒有爲備用資源提供最符合當前設備配置的限定符,則系統可能使用其中最匹配的資源。 如需瞭解有關如何處理不同屏幕密度以及 Android 如何縮放位圖以適應當前密度的詳細信息,請參閱支持多個屏幕。 |
觸摸屏類型 |
notouch finger |
另請參閱 |
鍵盤可用性 |
keysexposed keyshidden keyssoft |
如果提供了 如果用戶打開硬鍵盤,它有可能在應用生命週期中發生改變。 如需瞭解這會在運行期間給應用帶來哪些影響,請參閱處理運行時變更。 另請參閱配置字段 |
主要文本輸入法 |
nokeys qwerty 12key |
另請參閱 |
導航鍵可用性 |
navexposed navhidden |
如果用戶顯示導航鍵,它有可能在應用生命週期中發生改變。 如需瞭解這會在運行期間給應用帶來哪些影響,請參閱處理運行時變更。 另請參閱 |
主要非觸摸導航方法 |
nonav dpad trackball wheel |
另請參閱 |
平臺版本(API 級別) |
示例:v3 v4 v7 等等 |
設備支持的 API 級別。例如, |
注:有些配置限定符是從 Android 1.0 纔開始添加,因此並非所有版本的 Android 系統都支持所有限定符。使用新限定符會隱式添加平臺版本限定符,因此較舊版本系統的設備必然會忽略它。 例如,使用 w600dp 限定符會自動包括 v13 限定符,因爲可用寬度限定符是 API 級別 13 中的新增配置。爲了避免出現任何問題,請始終包含一組默認資源(一組“不帶限定符”的資源)。 如需瞭解詳細信息,請參閱利用資源提供最佳設備兼容性部分。
創建別名資源
如果您想將某一資源用於多種設備配置(但是不想作爲默認資源提供),則無需將同一資源放入多個備用資源目錄中。 相反,您可以(在某些情況下)創建備用資源,充當保存在默認資源目錄下的資源的別名。
注:並非所有資源都會提供相應機制讓您創建指向其他資源的別名。 特別是,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/ 中)的別名。
佈局
要創建指向現有佈局的別名,請使用包裝在 <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="yellow">#f00</color>
<color name="highlight">@color/red</color>
</resources>
利用資源提供最佳設備兼容性
要使應用支持多種設備配置,則務必爲應用使用的每種資源類型提供默認資源,這一點非常重要。
例如,如果應用支持多種語言,請始終包含不帶語言和區域限定符的 values/ 目錄(用於保存字符串)。相反,如果您將所有字符串放入帶有語言和區域限定符的目錄中,則在語言設置不支持您的字符串的設備上運行應用時,應用將會崩潰。 但是,只要提供默認 values/ 資源,應用就會正常運行(即使用戶不理解該語言,這也總比崩潰要好)。
同樣,如果您根據屏幕方向提供不同的佈局資源,則應選擇一個方向作爲默認方向。 例如,不要在 layout-land/ 和 layout-port/ 中分別提供橫向和縱向的佈局資源,而是保留其中之一作爲默認設置,例如:layout/ 用於橫向,layout-port/ 用於縱向。
提供默認資源至關重要,這不僅僅因爲應用可能在超出預期的配置上運行,也因爲新版 Android 有時會添加舊版本不支持的配置限定符。若要使用新的資源限定符,又希望維持對舊版 Android 的代碼兼容性,則當舊版 Android 運行應用時,如果不提供默認資源,應用將會崩潰,這是因爲它無法使用以新限定符命名的資源。例如,如果將 minSdkVersion 設置爲 4,並使用夜間模式(night 或 notnight,API 級別 8 中新增配置)限定所有 Drawable 資源,則 API 級別 4 設備無法訪問 Drawable 資源,而且會崩潰。在這種情況下,您可能希望 notnight 成爲默認資源,爲此,您應排除該限定符,使 Drawable 資源位於 drawable/ 或 drawable-night/ 中。
因此,爲了提供最佳設備兼容性,請始終爲應用正確運行所必需的資源提供默認資源。 然後,使用配置限定符爲特定的設備配置創建備用資源。
這條規則有一個例外:如果應用的 minSdkVersion 爲 4 或更高,則在提供帶屏幕密度限定符的備用 Drawable 資源時,不需要默認 Drawable 資源。 即使沒有默認 Drawable 資源,Android 也可以從備用屏幕密度中找到最佳匹配項並根據需要縮放位圖。 但是,爲了在所有類型的設備上提供最佳體驗,您應該爲所有三種類型的密度提供備用 Drawable。
Android 如何找到最匹配資源
當您請求要爲其提供備用資源的資源時,Android 會根據當前的設備配置選擇要在運行時使用的備用資源。爲演示 Android 如何選擇備用資源,假設以下 Drawable 目錄分別包含相同圖像的不同版本:
drawable/
drawable-en/
drawable-fr-rCA/
drawable-en-port/
drawable-en-notouch-12key/
drawable-port-ldpi/
drawable-port-notouch-12key/
同時,假設設備配置如下:
區域設置 = en-GB
屏幕方向 = port
屏幕像素密度 = hdpi
觸摸屏類型 = notouch
主要文本輸入法 = 12key
通過將設備配置與可用的備用資源進行比較,Android 從 drawable-en-port 中選擇 Drawable。
如圖2,系統使用以下邏輯決定要使用的資源:
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 傾向於縮小大型原始圖像,而不是放大小型原始圖像。
返回並重復第 2 步、第 3 步和第 4 步,直到只剩下一個目錄爲止。在此示例中,屏幕方向是下一個判斷是否匹配的限定符。因此,未指定屏幕方向的資源被淘汰:
drawable-en/
drawable-en-port/
drawable-en-notouch-12key/
剩下的目錄是 drawable-en-port。
儘管對所請求的每個資源均執行此程序,但是系統仍會對某些方面做進一步優化。 例如,系統一旦知道設備配置,即會淘汰可能永遠無法匹配的備用資源。 比如說,如果配置語言是英語(“en”),則系統絕不會將語言限定符設置爲非英語的任何資源目錄包含在選中的資源池中(不過,仍會將不帶語言限定符的資源目錄包含在該池中)。
5.根據屏幕尺寸限定符選擇資源時,如果沒有更好的匹配資源,則系統將使用專爲小於當前屏幕的屏幕而設計的資源(例如,如有必要,大尺寸屏幕將使用標準尺寸的屏幕資源)。 但是,如果唯一可用的資源大於當前屏幕,則系統不會使用這些資源,並且如果沒有其他資源與設備配置匹配,應用將會崩潰(例如,如果所有佈局資源均用 xlarge 限定符標記,但設備是標準尺寸的屏幕)。
注:限定符的優先順序(表 2 中)比與設備完全匹配的限定符數量更加重要。例如,在上面的第 4 步中,列表剩下的最後選項包括三個與設備完全匹配的限定符(方向、觸摸屏類型和輸入法),而 drawable-en 只有一個匹配參數(語言)。但是,語言的優先順序高於其他兩個限定符,因此 drawable-port-notouch-12key 被淘汰。