資源是程式碼使用的額外檔案和靜態內容,例如點陣圖、使用者介面字串和動畫指示等。
請一律將應用程式資源 (如圖片及字串) 與程式碼分開,以便個別維護這些資源。此外,請將替代資源歸類在已特別命名的資源目錄中,為特定裝置設定提供替代資源。Android 在執行階段會根據目前設定使用合適的資源。舉例來說,您可能會想根據語言設定提供不同的字串。
將應用程式資源外部化後,就可以使用在專案 R 分類中產生的資源 ID 存取這些資源。本文件說明如何替 Android 專案中的資源分組,以及如何為特定裝置設定提供額外資源,然後透過應用程式程式碼或其他 XML 檔案存取這些資源。
群組資源類型
請在專案 res/ 目錄的特定子目錄中放入各類型的資源。下列為簡易專案的檔案階層範例:
MyProject/
src/
MyActivity.kt
res/
drawable/
graphic.png
mipmap/
icon.png
values/
strings.xml
res/ 目錄包含子目錄中的所有資源:一個圖片資源、啟動器圖示的 mipmap/ 目錄,以及字串資源檔案。資源目錄名稱非常重要,表 1 將說明這些名稱。
注意:如需進一步瞭解如何使用 mipmap 資料夾,請參閱「將應用程式圖示放在 mipmap 目錄中」。
表 1 專案 res/ 目錄中支援的資源目錄。
| 目錄 | 資源類型 |
|---|---|
drawable/ |
點陣圖檔案 (PNG、
詳情請參閱「可繪製資源」。 |
mipmap/ |
適合不同啟動器圖示密度的可繪項目檔案。如要進一步瞭解如何使用 mipmap/ 資料夾管理啟動器圖示,請參閱「將應用程式圖示放在 mipmap 目錄中」。 |
raw/ |
要以原始格式儲存的任意檔案。如要使用原始 不過,如果您需要存取原始檔案名稱和檔案階層,請考慮將資源儲存在 |
values/ |
包含簡單值 (例如字串,整數以及顏色) 的 XML 檔案。 其他 因為每個資源是以自己的 XML 元素定義,所以您可以隨意命名檔案,也可以在一個檔案中放置不同的資源類型。不過,為了清楚起見,建議您將不重複的資源類型放入不同的檔案中。舉例來說,以下是一些可以在此目錄中建立的資源檔案名稱常見慣例: |
xml/ |
執行階段中呼叫 Resources.getXML 可讀取的任意 XML 檔案。各種 XML 設定檔都必須儲存在此。 |
font/ |
有副檔名的字型檔案 (例如 TTF、OTF 或 TTC),或包含 <font-family> 元素的 XML 檔案。如要進一步瞭解如何將字型做為資源,請參閱「將字型新增為 XML 資源」。 |
注意:請勿直接在 res/ 目錄中儲存資源檔案,否則會導致編譯器發生錯誤。
凡是儲存在表格 1 所定義子目錄中的資源,就是您的預設資源。也就是說,這些資源可定義應用程式的預設設計和內容。不過,不同類型的 Android 裝置可能會呼叫不同類型的資源。
舉例來說,您可以提供不同的字串資源,根據裝置的語言設定來翻譯使用者介面中的文字。
注意:在 Compose 中,UI、動畫和狀態驅動的顏色都是以 Kotlin 宣告,因此 layout/、menu/、anim/、animator/ 和 color/ 目錄已不適用於現代應用程式。詳情請參閱「Compose 中的動畫」和「Compose 主題的圖解」。
提供額外資源
大多數應用程式都會提供額外資源,用來支援特定的裝置設定,例如針對不同的螢幕密度和語言,分別提供額外可繪製資源和額外字串資源。Android 會在執行階段中偵測目前的裝置設定,並為您的應用程式載入合適的資源。
如要為一組資源指定適用於特定設定的額外資源,請依照以下步驟操作:
- 在
res/中以<resources_name>-<qualifier>格式建立新目錄。- 「
<resources_name>」是對應預設資源的目錄名稱 (如表 1 定義)。 - 「
<qualifier>」是一個名稱,可指定要使用這些資源的個別設定 (如表 2 所示)。
您可以附加多個「
<qualifier>」。請使用破折號分隔。注意:附加多個限定詞時,您必須按照表 2 的順序排列這些限定詞。如果限定詞的順序錯誤,系統就會忽略資源。
- 「
- 將相對應的額外資源儲存在這個新目錄中。資源檔案名稱必須與預設資源檔案名稱完全相同。
以下為一些預設以及額外資源範例:
res/
drawable/
icon.png
background.png
drawable-hdpi/
icon.png
background.png
hdpi 限定詞表示目錄中的資源是在高密度螢幕裝置使用。這些可繪項目目錄中的圖片大小皆是針對特定螢幕密度設計,不過檔案名稱完全相同。如此一來,您在參照 icon.png 或 background.png 圖片時使用的資源 ID 就會一律相同。Android 會比較裝置設定資訊與資源目錄名稱中的限定詞,逐一選擇最符合目前裝置的資源版本。
注意:定義額外資源時,請務必也在預設設定中定義資源。否則,裝置變更設定時,應用程式可能會發生執行階段例外狀況。舉例來說,如果只新增字串至 values-en,而非 values,那麼當使用者變更預設的系統語言時,應用程式可能會發生 Resource Not Found 例外狀況。
表 2 按照優先順序列出了設定限定詞。您可以在一個目錄名稱中加入多個限定詞,只要使用連字號分隔即可。如果資源目錄使用多個限定詞,您必須按照表中的次序將這些限定詞加進目錄名稱中。
表 2. 設定限定詞名稱
| 設定 | 限定詞的值 | 說明 |
|---|---|---|
| MCC 和 MNC | 例如:mcc310mcc208-mnc00
|
行動裝置國家/地區代碼 (MCC) 後面會選擇性加上裝置 SIM 卡上的行動網路識別碼 (MNC)。舉例來說, 如果裝置使用無線電連結功能 (GSM 手機),MCC 以及 MNC 的值會取自 SIM 卡。 您也可以單獨使用 MCC,例如在應用程式中加入特定國家/地區的法律資源時,就可以這麼做。如果只需要根據語言來指定,請改用「語言、指令碼 (選用) 和區域 (選用)」限定詞。如果您使用 MCC 和 MNC 限定詞,請小心留意,並測試是否能正常運作。 |
| 語言、指令碼 (選用) 和區域 (選用) | 例如:enfren-rUSfr-rFRfr-rCAb+enb+en+USb+es+419b+zh+Hantb+sr+Latn+RS |
語言是由兩個字母組成的 ISO 639-1 語言代碼所定義,後面會選擇性加上兩個字母組成的 ISO 3166-1-alpha-2 區碼 (前面加上小寫的 這些代碼「不」區分大小寫。 Android 7.0 (API 級別 24) 加入了對 BCP 47 語言標記的支援,讓您可以限定特定語言和地區專屬的資源。語言標記是由一或多個子標記所組成,每個子標記都會修正或縮小整體標記識別的語言範圍。如要進一步瞭解語言標記,請參閱「語言辨識標記」。 如要使用 BCP 47 語言標記,請串連 如果使用者在系統設定中變更語言,語言標記在應用程式的生命週期內可能會變更。如果想進一步瞭解這會在執行階段期間對應用程式造成什麼影響,請參閱「處理設定變更」。 如需將應用程式翻譯成其他語言的完整指南,請參閱「將應用程式本地化」。 另請參閱 |
| 語法性別 | masculinefeminineneuter |
使用者的語法性別。適用於有文法性別的語言。 舉例來說,如要為法語使用者提供不同資源,可以使用下列目錄:
請參閱「使用文法性別自訂應用程式的使用者介面」。 另請參閱 已加至 API 級別 34。 |
| 廣色域 |
widecgnowidecg
|
已加至 API 級別 26。 另請參閱 |
| 高動態範圍 (HDR) |
highdrlowdr
|
已加至 API 級別 26。 另請參閱 |
| UI 模式 |
cardesktelevisionappliancewatchvrheadset
|
已加至 API 級別 8、API 級別 13 (電視)、API 級別 16 (家電)、API 級別 20 (手錶)、API 級別 26 (VR 頭戴式裝置)。 如需進一步瞭解裝置插入座架或從座架移除時,您的應用程式可以如何回應,請參閱「判斷及監控座架狀態/類型」。 在應用程式生命週期內,這項設定會在使用者將裝置插入座架時改變。您可以透過 |
| 夜間模式 |
nightnotnight
|
已加至 API 級別 8。 採用自動模式 (預設) 的夜間模式會因時間而切換,因此在應用程式生命週期內,這項設定會隨之變化。您可以透過 |
| 螢幕像素密度 (dpi) |
ldpimdpihdpixhdpixxhdpixxxhdpinodpitvdpianydpinnndpi
|
這六個主要像素的縮放密度比為 3:4:6:8:12:16 (不包括 tvdpi 密度),所以,ldpi 螢幕中的 9x9 點陣圖在 mdpi 中會是 12x12,在 hdpi 中會是 18x18,在 xhdpi 中會是 24x24,以此類推。 注意:使用像素密度限定詞並不表示資源「只」適用於該密度的螢幕。如果您沒有為額外資源提供較符合目前裝置設定的限定詞,系統會使用任一最相符的資源。 如要進一步瞭解如何處理不同的螢幕密度,以及 Android 會如何縮放點陣圖來符合目前密度,請參閱「螢幕相容性總覽」。 |
| 觸控螢幕類型 |
notouchfinger
|
另請參閱 |
| 可用鍵盤 |
keysexposedkeyshiddenkeyssoft
|
如果您提供 在應用程式生命週期內,這項設定會因使用者開啟實體鍵盤而改變。如要進一步瞭解這在執行階段中對應用程式有何影響,請參閱「處理設定變更」。 另請參閱設定欄位 |
| 主要文字輸入法 |
nokeysqwerty12key
|
另請參閱 |
| 可用瀏覽鍵 |
navexposednavhidden
|
在應用程式生命週期內,如果使用者選擇顯示瀏覽鍵,這項設定就會隨之改變。如要進一步瞭解這在執行階段中對應用程式有何影響,請參閱「處理設定變更」。 另請參閱 |
| 主要非觸控瀏覽方式 |
nonavdpadtrackballwheel
|
另請參閱 |
| 平台版本 (API 級別) | 範例:v3v4v7等。 |
裝置支援的 API 級別。例如, |
注意:並非所有 Android 版本皆支援所有限定詞。使用新限定詞會間接新增該平台版本的限定詞,以便讓舊版裝置能忽略新限定詞。為避免發生問題,請務必加入一組預設資源 (一組「不含限定詞」的資源)。詳情請參閱「利用資源提供最佳裝置相容性」一節。
在 Compose 應用程式中,不需要與版面配置和尺寸相關的設定限定符。雖然這些查詢仍存在,但不會顯示在表 2 中。這些限定詞包括:版面配置方向、最小寬度、可用寬度、可用高度、螢幕大小、螢幕比例、圓形螢幕和螢幕方向。如需依優先順序排列的完整設定限定詞表格,請參閱「應用程式資源總覽 (檢視畫面)」。
限定詞名稱規則
以下是一些關於使用設定限定詞名稱的規則:
- 您可以為一組資源指定多個限定詞,只要用連字號隔開即可。舉例來說,
drawable-en-rUS-night適用於夜間模式的美式英文裝置。 - 限定詞必須按照表 2 的順序排列。
- 錯誤:
drawable-hdpi-night/ - 正確:
drawable-night-hdpi/
- 錯誤:
- 不得建立巢狀額外資源目錄。例如,您不能使用
res/drawable/drawable-en/。 - 值不區分大小寫。資源編譯器進行處理前會將目錄名稱轉換為小寫,避免不區分大小寫的檔案系統發生問題。名稱中如有任何大寫字母,只是為了方便閱讀。
- 每一種限定詞只支援一個值。舉例來說,如要針對西班牙和法國使用相同的可繪項目檔案,您就「不能」將目錄命名為
drawable-es-fr/,而是需要建立包含相應檔案的兩個資源目錄,例如drawable-es/和drawable-fr/。
將額外資源存入名稱中包含這些限定詞的目錄後,Android 會自動在應用程式中根據目前的裝置設定套用資源。每次要求資源時,Android 會查看包含所要求資源檔案的額外資源目錄,找出最相符的資源。
如果沒有額外資源符合該裝置設定,Android 會使用對應的預設資源,亦即一組不包含設定限定詞的特定類型資源。
建立別名資源
如果您想將某一資源用於多種裝置設定上,但不想以預設資源的方式提供,並不需要在多個額外資源目錄中放入同一個資源,而是可以改為建立一個替代資源,做為預設資源目錄中所存資源的別名。
可繪項目
舉例來說,假設您有應用程式圖示 icon.png,且需要針對不同的語言代碼提供專屬版本。但有兩個語言代碼需要使用相同的版本,分別是英文 (加拿大) 以及法文 (加拿大)。您不需要將相同圖片一併複製到英文 (加拿大) 及法文 (加拿大) 的資源目錄,而是可以將這兩種語言使用的圖片儲存為 icon.png「以外」 的任意名稱 (例如 icon_ca.png),然後放入預設的 res/drawable/ 目錄中。接著,只要在 res/drawable-en-rCA/ 和 res/drawable-fr-rCA/ 中建立 icon.xml 檔案,藉此使用 <bitmap> 元素參照 icon_ca.png 資源,
<?xml version="1.0" encoding="utf-8"?> <bitmap xmlns:android="http://schemas.android.com/apk/res/android" android:src="@drawable/icon_ca" />
就可以只儲存一種版本的 PNG 檔案,以及指向該 PNG 檔案的兩個 XML 小檔案。然後使用 painterResource(R.drawable.icon),系統偵測到語言代碼後,就會挑選適當的檔案。
字串以及其他簡單值
如要建立現有字串的別名,請將所需字串的資源 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="red">#f00</color> <color name="highlight">@color/red</color> </resources>
存取應用程式資源
在應用程式中提供資源後,您就可以參照資源 ID 來套用資源。所有資源 ID 都會在專案的 R 類別中定義,然後自動產生 aapt 工具。
當您編譯應用程式時,aapt 會產生 R 類別,其中包含 res/ 目錄中所有資源的資源 ID。每個資源類型都有 R 子類別,例如可繪製資源全都有 R.drawable。而該類型的每種資源都有靜態整數,例如 R.drawable.icon。此整數是資源 ID,可用來擷取資源。
雖然 R 類別是指定資源 ID 的位置,但您不需要在此尋找資源 ID。資源 ID 一律由下列項目組成:
- 「資源類型」:每個資源都會以「類型」分組,例如
string或drawable。 - 資源名稱:不含副檔名的檔案名稱。
在 Compose 中存取資源
Jetpack Compose 提供內建的函式,可安全存取資源,並支援可組合函式。
- 字串:
stringResource(id = R.string.hello)
- 可繪項目:
painterResource(id = R.drawable.my_icon)
在非 UI 程式碼中存取資源
如要存取 UI 階層以外的資源 (例如 ViewModel、Repository 或系統 Service),可以使用 Context 解析這些資源。
// Retrieve a localized string resource val greeting = context.getString(R.string.hello_world)
您也可以使用 Resources 中的方法 (使用 getResources 取得執行個體) 擷取個別資源。
語法
以下是在程式碼中參照資源的語法:
[<package_name>.]R.<resource_type>.<resource_name>
- 「
<package_name>」是資源所在的套件名稱 (參照套件中的資源時不需要)。 - 「
<resource_type>」是資源類型的R子類別。 - 「
<resource_name>」是不含副檔名的資源檔案名稱,如果是簡單值,則也可以是 XML 元素中的android:name屬性值。
如要進一步瞭解各種資源類型及其參照方式,請參閱「Compose 中的資源」。
存取原始檔案
在少數情況下,您可能需要存取原始檔案和目錄。如要執行這類操作,檔案並不合適儲存在 res/ 中,原因在於從 res/ 讀取資源的唯一方法是使用資源 ID。因此,您可以改為將資源儲存在 assets/ 目錄中。
儲存在 assets/ 目錄中的檔案「沒有」資源 ID,因此您無法透過 R 類別或 XML 資源參照這些檔案。您可以改為像一般檔案系統一樣查詢 assets/ 目錄中的檔案,然後使用 AssetManager 讀取原始資料。
不過,如果您只需要讀取原始資料 (例如:影片或音訊檔案),請將檔案儲存在 res/raw/ 目錄中,然後使用 openRawResource 讀取位元組串流。
存取平台資源
Android 包含多個標準資源,例如系統樣式和主題。如要存取這些資源,請使用 android 套件類別設定資源參照。例如:painterResource(android.R.drawable.ic_menu_info_details)。
利用資源提供最佳裝置相容性
為了讓應用程式可以支援多種裝置設定,請務必一律為應用程式所用的資源逐一提供預設資源。
舉例來說,如果應用程式支援多種語言,請務必加入 values/ 目錄 (字串的儲存位置),但「不要」有語言和地區限定詞。反之,如果您是將所有字串檔案放在帶有語言及地區限定詞的目錄中,且裝置設為字串所不支援的語言,應用程式在該裝置執行時就會當機。
只要您提供預設的 values/ 資源,即便使用者不懂系統顯示的語言,應用程式也會正常運作。這樣總比應用程式當機要好。
提供預設資源非常重要,這不僅是因為應用程式可能會在您預期之外的設定中執行,也是因為新版本的 Android 有時會加入舊版不支援的設定限定詞所致。如果您使用新的資源限定詞,但代碼仍與舊版 Android 相容,較舊版本的 Android 就無法使用以新限定詞命名的資源,因此在沒有預設資源的情況下執行應用程式就會當機。
舉例來說,如果 minSdkVersion 設為 4,且限定所有可繪製資源使用夜間模式 (night 或 notnight,已加至 API 級別 8),API 級別 4 裝置便無法存取可繪製資源,且會造成當機。在這種情況下,您可能會想使用 notnight 做為預設資源,因此請排除該限定詞,並將可繪製資源放入 drawable/ 或 drawable-night/ 中。
簡言之,為了提供最佳的裝置相容性,請一律提供預設資源,讓應用程式具備順利執行所需的資源。接著使用設定限定詞,針對特定的裝置設定建立額外資源。
以下為例外情況:如果應用程式的 minSdkVersion 為 4 以上,則使用螢幕密度限定詞提供額外可繪製資源時「不需要」預設可繪製資源。即使沒有預設的可繪製資源,Android 依然可以在額外螢幕密度中找到最相符的資源,並在必要時調整點陣圖大小。然而,為了讓所有裝置類型的使用者都能享有最佳體驗,三種螢幕密度都應該提供額外可繪項目。
Android 如何尋找最相符的資源
當您要求資源以提供額外資源時,Android 會根據目前的裝置設定要在執行階段使用的額外資源。以下範例示範 Android 如何選擇額外資源;假設下列可繪項目目錄各包含不同版本的相同圖片:
drawable/ drawable-en/ drawable-fr-rCA/ drawable-en-night/ drawable-en-notouch-12key/ drawable-night-ldpi/ drawable-night-notouch-12key/
並假設下列為該裝置的設定:
語言代碼 = en-GB
夜間模式 = night
螢幕像素密度 = hdpi
觸控螢幕類型 = notouch
主要文字輸入法 = 12key
比較裝置設定與可用額外資源後,Android 會從 drawable-en-night 選擇可繪項目。
然後系統會決定要使用的資源,邏輯如下:
圖 2. Android 找出最相符資源的流程圖。
- 排除與裝置設定相牴觸的資源檔案。
drawable-fr-rCA/目錄排除,因為與en-GB語言代碼牴觸。drawable/ drawable-en/
drawable-fr-rCA/drawable-en-night/ drawable-en-notouch-12key/ drawable-night-ldpi/ drawable-night-notouch-12key/例外:螢幕像素密度是唯一不會因牴觸而排除的限定詞。即使裝置的螢幕密度為 hdpi,
drawable-night-ldpi/也不會排除,這是因為目前每個螢幕密度都會視為相符。詳情請參閱「螢幕相容性總覽」。 - 選出清單 (表 2) 中優先順序次高的限定詞 (從 MCC 開始)。
- 是否有任何資源目錄包含此限定詞?
- 如果沒有,請回到步驟 2 查看下一個限定詞。在此範例中,語言限定詞以前的答案皆為「沒有」。
- 如果有,請前往步驟 4。
- 排除不包含此限定詞的資源目錄。在此範例中,系統接下來會排除所有不包含語言限定詞的目錄:
drawable/drawable-en/ drawable-en-night/ drawable-en-notouch-12key/drawable-night-ldpi/drawable-night-notouch-12key/例外狀況:如果上述的限定詞為螢幕像素密度,Android 會選擇最接近該裝置螢幕密度的選項。一般來說,比起放大較小原圖,Android 偏好縮小較大原圖。詳情請參閱「螢幕相容性總覽」。
- 重複步驟 2、3 和 4,直到僅剩一個目錄為止。在本例中,夜間模式是下一個有相符項目的限定詞。因此,沒有指定夜間模式的資源會遭到排除:
drawable-en/drawable-en-night/drawable-en-notouch-12key/剩餘的目錄是
drawable-en-night。
雖然系統會對每個要求的資源執行此流程,不過仍會對某些部分進行最佳化。其中一項最佳化是在知道裝置設定後,可能會排除永遠不會相符的額外資源。舉例來說,如果設定語言為「英文」(「en」),任何將語言限定詞設為「英文」以外語言的資源目錄,就絕不會納入已檢查的資源集區中 (但「不含」語言限定詞的資源目錄仍會納入)。
根據螢幕大小限定詞選擇資源時,如果沒有其他更符合的資源,系統會使用為較小螢幕設計的資源。舉例來說,大螢幕會在必要時使用一般大小的螢幕資源。
不過,如果唯一可用的資源比目前螢幕「大」,系統就不會使用這些資源;此外,假如沒有其他資源符合裝置設定,應用程式還會當機。舉例來說,如果所有版面配置資源都是以 xlarge 限定詞標記,但裝置使用一般大小螢幕,就會發生上述情況。
注意:限定詞的「優先順序」(表 2) 比與裝置完全相符的限定詞數量還更重要。在上述範例的步驟 4 中,列出的最後一個選項包含三個與裝置完全相符的限定詞 (夜間模式、觸控螢幕類型以及輸入法),而 drawable-en 只有一個符合的參數 (語言)。不過,由於語言的優先順序高於這些限定詞,因此系統會排除 drawable-night-notouch-12key。
其他資源
如要進一步瞭解應用程式資源,請參閱下列其他資源: