原文:Understanding App Resources
—Understanding Strings and Resources
概述
在Android中,幾乎一切事物都是資源。定義在應(yīng)用程序中可訪問的資源,是Android開發(fā)的一個(gè)重要部分。
資源用于定義顏色、圖像、布局、菜單和字符串值。這樣做的意義是可以使不良的“硬編碼”習(xí)慣消失。所有內(nèi)容分別定義在這些資源文件中,可以被應(yīng)用程序中的代碼引用。這些資源最簡(jiǎn)單和最常見的用法是使用字符串資源,實(shí)現(xiàn)靈活的本地化文本。
資源類型
以下是Android應(yīng)用中最常用的資源類型:
Name | Folder | Description |
---|---|---|
Property Animations(屬性動(dòng)畫) | animator | 定義屬性動(dòng)畫的XML文件 |
Tween Animations(補(bǔ)間動(dòng)畫) | anim | 定義補(bǔ)間動(dòng)畫的XML文件 |
Drawables | drawable | 位圖文件或作為圖像的XML文件 |
Layout | layout | 定義用戶接口布局的XML文件 |
Menu | menu | 定義菜單或動(dòng)作欄的XML文件 |
Values | values | 使用string,integer或color的XML文件 |
另外,注意以下定義在values
文件夾下的關(guān)鍵文件:
Name | File | Description |
---|---|---|
Colors | res/values/colors.xml |
顏色定義,例如文本顏色 |
Dimensions | res/values/dimens.xml |
尺寸值,例如內(nèi)邊距 |
Strings | res/values/strings.xml |
字符串值,例如文本標(biāo)題 |
Styles | res/values/styles.xml |
樣式值,例如AppBar的顏色 |
想了解資源類型的完整列表,請(qǐng)參考Providing a Resource指南。
為應(yīng)用提供資源
定義字符串資源
對(duì)于你要在應(yīng)用中展示的每一段文本(例如按鈕的標(biāo)簽或TextView上的文字),你應(yīng)該先將文本定義在res/values/strings.xml
文件中。每個(gè)條目包含一個(gè)“鍵”(代表文本的標(biāo)識(shí))和一個(gè)“值”(文本本身)。例如,如果你想在按鈕上展示“Submit”,你應(yīng)該想如下的字符串資源添加到res/values/strings.xml
文件中:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello!</string>
<string name="submit_label">Submit</string>
</resources>
現(xiàn)在我如果引用了submit_label
字符串資源,默認(rèn)地將會(huì)顯示“Submit”。稍后,你可以創(chuàng)建全匹配的資源文件,以針對(duì)不同的系統(tǒng)語言或設(shè)備更改此值。我們還可以使用CDATA來轉(zhuǎn)義字符串,以存儲(chǔ)更復(fù)雜的字符串(帶有html標(biāo)簽或特殊字符),例如:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="feedback_label">
<![CDATA[
Please <a >let us know</a> if you have feedback on this or if
you would like to log in with another identity service. Thanks! This is a longer string!
]]>
</string>
</resources>
對(duì)于字符串資源定義的更多細(xì)節(jié),請(qǐng)參考本篇指南。你還可以參考指南中的樣式資源和其他資源類型。
在應(yīng)用中引用資源
既然我們已經(jīng)定義好了自己的字符串資源,我們就能夠在Java代碼或者XML布局文件中訪問這些資源。要在XML布局文件中訪問資源,要使用@語法:
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/submit_label" />
要在Java代碼中直接訪問資源,需要使用getResources.getString
或 getString
方法,訪問給定資源ID的值:
String submitText = getResources().getString(R.string.submit_label)
字符串值將會(huì)被檢索。其他資源類型也采用了類似的工作機(jī)制,比如Drawable和Color等。getResourses()
方法返回一個(gè)包含許多資源提取方法的Resources對(duì)象。每一種資源定義在res
目錄下的不同文件夾和文件中,這由它們的具體類型所決定。
定義顏色資源
除了上邊展示的字符串資源,還有以下常見的資源類型。首先,讓我們看一下用于定義整個(gè)應(yīng)用中所有顏色的顏色資源文件。顏色資源在res/values/colors.xml
中定義,XML文件的樣式如下所示:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="white">#FFFFFF</color>
<color name="yellow">#FFFF00</color>
<color name="fuchsia">#FF00FF</color>
</resources>
顏色資源可以在Java代碼中訪問:
// getResources().getColor():該方法目前被廢棄
// Resources res = getResources();
// int color = res.getColor(R.color.yellow);
// 使用ContextCompatResources
int color = ContextCompat.getColor(context, R.color.yellow);
值得注意的是,當(dāng)前最新的訪問顏色資源的方式(自從API 24開始),要求提供context來解析自定義的Theme屬性。參閱這篇文章了解更多的相關(guān)內(nèi)容。
并且在XML布局中的任意View引用顏色資源如下所示:
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="@color/fuchsia"
android:text="Hello"/>
&esmp;這是關(guān)于顏色資源你所要知道的全部?jī)?nèi)容,一定不要在布局文件中使用“硬編碼”的顏色值。
定義尺寸資源
接下來,我們來看一下用于定義整個(gè)應(yīng)用中所有尺寸大小的尺寸資源文件。一個(gè)尺寸由一個(gè)數(shù)字后邊跟測(cè)量單位來指定。例如10px
,5sp
。尺寸資源在res/values/dimens.xml
文件中定義,XML文件中的樣式如下所示:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="textview_height">25dp</dimen>
<dimen name="textview_width">150dp</dimen>
<dimen name="ball_radius">30dp</dimen>
<dimen name="font_size">16sp</dimen>
</resources>
尺寸資源可以在Java代碼中訪問:
Resources res = getResources();
float fontSize = res.getDimension(R.dimen.font_size);
并且在XML布局中的任意View引用尺寸資源如下所示:
<TextView
android:layout_height="@dimen/textview_height"
android:layout_width="@dimen/textview_width"
android:textSize="@dimen/font_size"/>
這是關(guān)于尺寸資源你所要了解的全部?jī)?nèi)容。一定要以這種方式定義字體大小、內(nèi)間距和外邊距值,避免“硬編碼”方式出現(xiàn)。這是有關(guān)的其他資源類型。
動(dòng)態(tài)資源檢索
在某些情況下,你可能想通過鍵名稱而非“硬編碼”的資源ID來動(dòng)態(tài)檢索資源。例如,假設(shè)我想通過單獨(dú)的鍵名稱來檢索“submit_label”字符串,就可以通過Activity中的getIdentifier
方法實(shí)現(xiàn):
public String getStringValue(String key) {
//檢索資源ID
String packageName = getBaseContext().getPackageName();
Resources resources = getBaseContext().getResources();
int stringId = resources.getIdentifier(key, "string", packageName);
if (stringId == 0) { return null; }
//基于資源ID返回字符串值
return resources.getString(stringId);
}
現(xiàn)在你就可以動(dòng)態(tài)的引用字符串資源了:
public String myKey = "submit_label"; // 映射到R.string.submit_label
public String myStringValue = getStringValue(myKey); // Returns string text
類似的方法也能被用在其他類型的資源上。例如,通過字符串類型的ID動(dòng)態(tài)檢索View:
// getViewById("tvTest");
public View getViewById(String id) {
//檢索資源ID
String packageName = getBaseContext().getPackageName();
Resources resources = getBaseContext().getResources();
int viewId = resources.getIdentifier(id, "id", packageName);
if (viewId == 0) { return null; }
return findViewById(viewId);
}
查看getResources對(duì)象和<a href="http://developer.android.com/reference/android/content/res/Resources.html#getIdentifier(java.lang.String, java.lang.String, java.lang.String)">getIdentifier</a>獲取更多詳細(xì)信息。
提供可替代的資源
響應(yīng)式設(shè)計(jì)
為了實(shí)現(xiàn)出色的UI設(shè)計(jì),對(duì)于Android開發(fā)者來說,創(chuàng)建可在多種類型的備上正常工作的應(yīng)用是非常重要的。為實(shí)現(xiàn)這個(gè)目的,我們首先要根據(jù)屏幕尺寸將Android設(shè)備分為以下不同的種類:
應(yīng)用必須設(shè)計(jì)成可在多種不同的屏幕密度和屏幕尺寸上正常運(yùn)行。這可借助于Android框架提供的各種系統(tǒng)實(shí)現(xiàn)。
介紹可替代資源
開發(fā)者能夠使用的強(qiáng)大開發(fā)工具之一是,可根據(jù)特定的限定符如手機(jī)尺寸,系統(tǒng)語言,屏幕密度等提供“替代資源”。替代資源的常見用途包括:
- 用于不同外形設(shè)備的替代布局文件(如手機(jī)VS平板)
- 用于不同系統(tǒng)語言的替代字符串資源(如英語VS意大利語)
- 用于不同屏幕密度的替代圖像資源
- 用于不同平臺(tái)版本的替代樣式資源(Holo VS Material)
- 用于不同屏幕方向的替代布局文件(portrait VS landscape)
要為一組資源指定基于特定配置下的替代資源,我們?cè)?code>res中以[資源類型]-[限定符]
的形式創(chuàng)建一個(gè)新的目錄。一個(gè)最佳的實(shí)踐是確保為多種密度的屏幕提供了所有可適配的圖像。

這是通過包含具有相同圖像不同版本的res/drawable-hdpi
, res/drawable-xhdpi
, and res/drawable-xxhdpi
文件夾實(shí)現(xiàn)的。正確的資源會(huì)根據(jù)設(shè)備的屏幕密度被系統(tǒng)自動(dòng)選中。目錄的列表展開可能會(huì)如下所示:
res/
drawable/
icon.png
background.png
drawable-hdpi/
icon.png
background.png
注意所有不同文件夾下的資源文件都要有相同的名字。該系統(tǒng)適用于具有限定符的任意類型的資源。
理解限定符
Android支持多種限定符的配置,并且可以使用短線分隔限定符的方式,將多個(gè)限定符添加到一個(gè)目錄名稱。常用的限定符如下所示:
Configuration | Examples | Description |
---|---|---|
Language |
en , fr
|
設(shè)備上選中的語言代碼 |
Screen size |
sw480dp ,sw600dp
|
屏幕高度或者寬度的最小寬度 |
Screen orientation |
port , land
|
屏幕是出于橫屏或豎屏模式 |
Screen density |
hdpi , xhdpi
|
常用于可替代的圖片 |
Platform version |
v7 , v11 , v21
|
常用于樣式 |
你可以為單獨(dú)的一組資源,使用短線分隔方式指定多個(gè)限定符。例如,drawable-en-sw600dp-land
用于英文系統(tǒng)的橫屏模式下的平板設(shè)備。注意如果你對(duì)一個(gè)資源目錄使用了多個(gè)限定符,在將它們添加到目錄名中時(shí)一定要按照上表中所列出的順序。參閱完整限定符集的官方文檔。
創(chuàng)建可替代資源
在Android Studio中,創(chuàng)建可替代資源最簡(jiǎn)單的方式是在Android項(xiàng)目邊欄中的資源子目錄上右擊(例如layout),使用New => Layout resource file
方法指定你期望的限定符(例如orientation
):
這將會(huì)創(chuàng)建兩個(gè)版本的布局文件,一個(gè)用于豎屏模型,一個(gè)用于橫屏模式。如果你為第二個(gè)版本的布局文件添加了不同的標(biāo)簽,在屏幕方向旋轉(zhuǎn)時(shí)你將發(fā)現(xiàn)這個(gè)效果會(huì)自動(dòng)觸發(fā):
總結(jié)一下,你可以創(chuàng)建適用于不同情景下的多個(gè)資源文件版本,最合適的版本會(huì)被系統(tǒng)自動(dòng)選中使用。
在運(yùn)行時(shí)確定配置
當(dāng)應(yīng)用正在運(yùn)行時(shí),我們可以通過Activity或Context對(duì)象的getResources().getConfiguration()
方法訪問Configuration對(duì)象來檢測(cè)當(dāng)前的配置(方向,屏幕尺寸等)。例如,想要確定Activity中的屏幕方向(橫屏或豎屏),我們通過以下方式實(shí)現(xiàn):
String image;
int orientation = getResources().getConfiguration().orientation;
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
image = "image_portrait.png";
// ...
} else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
image = "image_landscape.png";
// ...
}
類似地我們可通過訪問一個(gè)Context對(duì)象在任何對(duì)象中訪問它。例如,在ArrayAdapter
中使用getContext().getResources().getConfiguration()
方法獲取配置。
備用布局文件
通常,替代資源用于為手機(jī)和平板指定不同的布局文件。這可以通過使用“最小寬度”限定符sw
實(shí)現(xiàn)。文件夾結(jié)構(gòu)可能設(shè)置如下:
res/
layout/
activity_main.xml
item_photo.xml
layout-sw600dp/
activity_main.xml
layout-sw600dp-land/
activity_main.xml
layout-sw720dp/
activity_main.xml
item_photo.xml
layout-land/
activity_main.xml
item_photo.xml
一般來說,手機(jī)和平板在sw240
和sw480
之間。7英寸平板為sw600
,10英寸平板為sw720
。你也可以簡(jiǎn)單地添加限定符如layout-land
,以橫屏模式應(yīng)用于所有設(shè)備。這是針對(duì)上述說明的一個(gè)例子:
有關(guān)如何管理平板設(shè)備的響應(yīng)式布局的指南,請(qǐng)參閱靈活的用戶接口
指南。你也可以參閱這篇文章UI設(shè)計(jì)最佳實(shí)踐和有關(guān)資源的官方文檔 獲取更多細(xì)節(jié)信息。
最佳布局實(shí)踐
這有一個(gè)快速檢查清單,可確保你的應(yīng)用可以在不同的屏幕上正常展示:
- 避免在應(yīng)用代碼中使用硬編碼的像素值
- 合理使用
RelativeLayout
,絕不使用AbsoluteLayout
- 指定尺寸值時(shí),使用
wrap_content
,match_parent
, 或dp
單位 - 為確保響應(yīng)式的設(shè)計(jì),使用替代布局和圖像資源
在官方指南上查看屏幕獨(dú)立性的其他最佳實(shí)踐。
資源別名
當(dāng)你想在多個(gè)設(shè)備配置中使用同一個(gè)資源時(shí),你不必將同一個(gè)資源文件在替代資源文件夾中拷貝多份。相反,你可以創(chuàng)建替代資源,作為保存在默認(rèn)資源目錄中的資源別名。
最佳資源匹配
當(dāng)你請(qǐng)求替代資源時(shí),Android會(huì)基于當(dāng)前設(shè)備的配置在運(yùn)行時(shí)選擇替代資源。參閱 官方資源指南了解匹配資源如何被選中的詳細(xì)概述。
參考引用
- http://developer.android.com/guide/topics/resources/string-resource.html
- http://developer.android.com/guide/topics/resources/accessing-resources.html
- http://mobile.tutsplus.com/tutorials/android/android-string/
- http://developer.android.com/guide/topics/resources/providing-resources.html
- http://developer.android.com/training/multiscreen/screendensities.html
- http://www.evoketechnologies.com/blog/effective-ui-design-tips-android-devices/
- http://www.androiddesignpatterns.com/2016/08/contextcompat-getcolor-getdrawable.html/