[Android][主題和樣式]

1.落筆緣由

本文主要是對(duì)Android主題和樣式的研究,本文主要是以摘抄官方文檔(地址在參考文章中給出)的內(nèi)容,在每段結(jié)尾進(jìn)行總結(jié)的形式來(lái)了解Android主題和樣式。

2.什么是樣式,主題

樣式是指為 View 或窗口指定外觀和格式的屬性集合。樣式可以指定高度、填充、字體顏色、字號(hào)、背景色等許多屬性。 樣式是在與指定布局的 XML 不同的 XML 資源中進(jìn)行定義。
Android 中的樣式與網(wǎng)頁(yè)設(shè)計(jì)中層疊樣式表的原理類似 — 您可以通過(guò)它將設(shè)計(jì)與內(nèi)容分離。
例如,通過(guò)使用樣式,您可以將以下布局 XML:

<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textColor="#00FF00"
    android:typeface="monospace"
    android:text="@string/hello" />

簡(jiǎn)化成這個(gè)樣子:

<TextView
    style="@style/CodeFont"
    android:text="@string/hello" />

布局 XML 中所有與樣式有關(guān)的屬性都已移除,并置于一個(gè)名為 CodeFont 的樣式定義內(nèi),然后通過(guò) style 屬性加以應(yīng)用。 您會(huì)在下文中看到對(duì)該樣式的定義。
主題是指對(duì)整個(gè) Activity 或應(yīng)用而不是對(duì)單個(gè) View(如上例所示)應(yīng)用的樣式。 以主題形式應(yīng)用樣式時(shí),Activity 或應(yīng)用中的每個(gè)視圖都將應(yīng)用其支持的每個(gè)樣式屬性。 例如,您可以 Activity 主題形式應(yīng)用同一 CodeFont 樣式,之后該 Activity 內(nèi)的所有文本都將具有綠色固定寬度字體。
簡(jiǎn)單來(lái)說(shuō)樣式是相對(duì)于View等控件來(lái)說(shuō)的,相當(dāng)于web中的css。而主題是相對(duì)于Activity來(lái)說(shuō)的,主題不單止是對(duì)Activity的生命周期(例如定義了ActivityB透明背景, 當(dāng)Activity A啟動(dòng)Activity B, A不透明,B透明,那么 A的onStop不會(huì)被調(diào)用,只會(huì)調(diào)用onPause。相當(dāng)于啟動(dòng)了一個(gè)dialog。)和轉(zhuǎn)場(chǎng)動(dòng)畫(huà)有影響,還有可能影響到Activity界面里的View控件,dialog樣式和popupWindow。

3.如何定義樣式

要?jiǎng)?chuàng)建一組樣式,請(qǐng)?jiān)谀捻?xiàng)目的 res/values/ 目錄中保存一個(gè) XML 文件。 可任意指定該 XML 文件的名稱,但它必須使用 .xml 擴(kuò)展名,并且必須保存在 res/values/ 文件夾內(nèi)。
該 XML 文件的根節(jié)點(diǎn)必須是 <resources>。
對(duì)于您想創(chuàng)建的每個(gè)樣式,向該文件添加一個(gè) <style> 元素,該元素帶有對(duì)樣式進(jìn)行唯一標(biāo)識(shí)的 name 屬性(該屬性為必需屬性)。然后為該樣式的每個(gè)屬性添加一個(gè) <item> 元素,該元素帶有聲明樣式屬性以及屬性值的 name(該屬性為必需屬性)。 根據(jù)樣式屬性,<item> 的值可以是關(guān)鍵字字符串、十六進(jìn)制顏色值、對(duì)另一資源類型的引用或其他值。以下是一個(gè)包含單個(gè)樣式的示例文件:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="CodeFont" parent="@android:style/TextAppearance.Medium">
        <item name="android:layout_width">fill_parent</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:textColor">#00FF00</item>
        <item name="android:typeface">monospace</item>
    </style>
</resources>

<resources> 元素的每個(gè)子項(xiàng)都會(huì)在編譯時(shí)轉(zhuǎn)換成一個(gè)應(yīng)用資源對(duì)象,該對(duì)象可由 <style> 元素的 name 屬性中的值引用。 可從 XML 布局以 @style/CodeFont 形式引用該示例樣式(如上文引言中所示)。
<style> 元素中的 parent 屬性是可選屬性,它指定應(yīng)作為此樣式所繼承屬性來(lái)源的另一樣式的資源 ID。 如果愿意,您可在隨后替換這些繼承的樣式屬性。
切記,在 XML 中定義您想用作 Activity 或應(yīng)用主題的樣式與定義視圖樣式的方法完全相同。 諸如上文所定義的樣式可作為單個(gè)視圖的樣式加以應(yīng)用,也可作為整個(gè) Activity 或應(yīng)用的主題加以應(yīng)用。 后文將闡述如何為單個(gè)視圖應(yīng)用樣式或如何以應(yīng)用主題形式應(yīng)用樣式。
簡(jiǎn)單來(lái)說(shuō):
(1) 在res/value目錄下創(chuàng)建一個(gè)xml文件,該文件名可以隨意命名(當(dāng)然了,前提還是要遵守命名規(guī)則)。
(2) 在 XML 中定義您想用作 Activity 或應(yīng)用主題的樣式與定義視圖樣式的方法完全相同。

1)繼承

您可以通過(guò) <style> 元素中的 parent 屬性指定應(yīng)作為您的樣式所繼承屬性來(lái)源的樣式。您可以利用它來(lái)繼承現(xiàn)有樣式的屬性,然后只定義您想要更改或添加的屬性。 您可以從自行創(chuàng)建的樣式或平臺(tái)內(nèi)建的樣式繼承屬性。 (如需了解有關(guān)從 Android 平臺(tái)定義的樣式繼承屬性的信息,請(qǐng)參閱下文的使用平臺(tái)樣式和主題。) 例如,您可以繼承 Android 平臺(tái)的默認(rèn)文本外觀,然后對(duì)其進(jìn)行修改:

    <style name="GreenText" parent="@android:style/TextAppearance">
        <item name="android:textColor">#00FF00</item>
    </style>

如果您想從自行定義的樣式繼承屬性,則不必使用 parent 屬性, 而是只需將您想繼承的樣式的名稱以前綴形式添加到新樣式的名稱之中,并以句點(diǎn)進(jìn)行分隔。 例如,要?jiǎng)?chuàng)建一個(gè)繼承上文定義的 CodeFont 樣式的新樣式,但將顏色設(shè)置為紅色,您可以按如下方式創(chuàng)建這個(gè)新樣式:

    <style name="CodeFont.Red">
        <item name="android:textColor">#FF0000</item>
    </style>

請(qǐng)注意,<style> 標(biāo)記中沒(méi)有 parent 屬性,但由于 name 屬性以 CodeFont 樣式名稱(這是您創(chuàng)建的一個(gè)樣式)開(kāi)頭,因此這個(gè)樣式會(huì)繼承該樣式的所有樣式屬性。 這個(gè)樣式隨后會(huì)替換 android:textColor 屬性,將文本設(shè)置為紅色。 您可以 @style/CodeFont.Red 形式引用這個(gè)新樣式。
您可以通過(guò)使用句點(diǎn)鏈接名稱繼續(xù)進(jìn)行這樣的繼承,次數(shù)不限。 例如,您可以通過(guò)以下代碼將 CodeFont.Red 擴(kuò)大:

    <style name="CodeFont.Red.Big">
        <item name="android:textSize">30sp</item>
    </style>

這段代碼同時(shí)從 CodeFont 和 CodeFont.Red 樣式繼承,然后添加 android:textSize 屬性。
簡(jiǎn)單來(lái)說(shuō):
(1)自定義樣式和系統(tǒng)樣式的繼承方式是不一樣的,自定義樣式可以通過(guò)點(diǎn)“.”來(lái)實(shí)現(xiàn)繼承,而系統(tǒng)樣式必須通過(guò)parent 屬性來(lái)繼承。

2)樣式屬性

相應(yīng)的類引用最便于查找適用于特定 View 的屬性,其中列出了所有支持的 XML 屬性。 例如,TextView XML 屬性表中所列的所有屬性都可在 TextView 元素(或其其中一個(gè)子類)的樣式定義中使用。 該引用中列出的其中一個(gè)屬性是 android:inputType,因此,如果您正常情況下會(huì)在 <EditText> 元素中放置 android:inputType 屬性,如下所示:

<EditText
    android:inputType="number"
    ... />

您就可以改為給包括該屬性的 EditText 元素創(chuàng)建一個(gè)樣式:

<style name="Numbers">
  <item name="android:inputType">number</item>
  ...
</style>

這樣您的布局 XML 現(xiàn)在便可實(shí)現(xiàn)這個(gè)樣式:

<EditText
    style="@style/Numbers"
    ... />

這個(gè)簡(jiǎn)單示例可能顯得工作量更大,但如果您添加更多樣式屬性并將能夠在各種地方重復(fù)使用樣式這一因素考慮在內(nèi),就會(huì)發(fā)現(xiàn)回報(bào)可能很豐厚。
如需查看所有可用樣式屬性的參考資料,請(qǐng)參閱 R.attr 參考資料。 切記,所有 View 對(duì)象仍然不接受樣式屬性,因此正常情況下您應(yīng)該引用所支持樣式屬性的具體 View 類。 不過(guò),如果您應(yīng)用樣式的 View 不支持所有樣式屬性,該 View 將只應(yīng)用那些受支持的屬性,并直接忽略其他屬性。
不過(guò),某些樣式屬性任何 View 元素都不提供支持,只能以主題形式應(yīng)用。 這些樣式屬性應(yīng)用于整個(gè)窗口而非任何類型的 View。例如,主題的樣式屬性可以隱藏應(yīng)用標(biāo)題、隱藏狀態(tài)欄或更改窗口的背景。 這些類型的樣式屬性不屬于任何 View 對(duì)象。要發(fā)現(xiàn)這些僅主題樣式屬性,請(qǐng)?jiān)?R.attr 參考資料中查看有關(guān)以 window 開(kāi)頭的屬性的內(nèi)容。 例如,windowNoTitle 和 windowBackground 是只有在樣式以主題形式應(yīng)用于 Activity 或應(yīng)用時(shí)才起作用的樣式屬性。 請(qǐng)參閱下文有關(guān)以主題形式應(yīng)用樣式的信息。
簡(jiǎn)單來(lái)說(shuō):

(1) 并不是所有的樣式屬性都能被View使用的,例如windowNoTitle等樣式屬性View是無(wú)法識(shí)別的。所以對(duì)于View不支持的樣式屬性,View會(huì)忽略掉它們,只將那些View支持的樣式屬性應(yīng)用到View上。
(2) 如何判斷View支持哪些屬性,可以到View的api下,查看它的xml屬性
如下圖

image.png

(3) R.attr里有所有的樣式屬性。
(4) 在R.attr里,如果要查看僅主題樣式可使用的屬性,那么查看有關(guān)以 window 開(kāi)頭的屬性的內(nèi)容。

4. 如何使用自定義樣式和主題樣式

設(shè)置樣式的方法有兩種:
? 如果是對(duì)單個(gè)視圖應(yīng)用樣式,請(qǐng)為布局 XML 中的 View 元素添加 style 屬性。
? 或者,如果是對(duì)整個(gè) Activity 或應(yīng)用來(lái)應(yīng)用樣式,請(qǐng)為 Android 清單中的 <activity> 或 <application> 元素添加 android:theme 屬性。
當(dāng)您對(duì)布局中的單個(gè) View 應(yīng)用樣式時(shí),該樣式定義的屬性只應(yīng)用于該 View。 如果對(duì) ViewGroup 應(yīng)用樣式,子 View元素將不會(huì)繼承樣式屬性 — 只有被您直接應(yīng)用樣式的元素才會(huì)應(yīng)用其屬性。 不過(guò),您可以通過(guò)以主題形式應(yīng)用樣式,使所應(yīng)用的樣式作用于所有 View 元素。
要以主題形式應(yīng)用樣式定義,您必須在 Android 清單中將樣式應(yīng)用于 Activity 或應(yīng)用。 如果您這樣做,Activity 或應(yīng)用內(nèi)的每個(gè) View 都將應(yīng)用其支持的每個(gè)屬性。 例如,如果您對(duì)某個(gè) Activity 應(yīng)用前面示例中的 CodeFont 樣式,則所有支持這些文本樣式屬性的 View 元素也會(huì)應(yīng)用這些屬性。 任何不支持這些屬性的 View 都會(huì)忽略這些屬性。 如果某個(gè) View 僅支持部分屬性,將只應(yīng)用這些屬性。

1)對(duì)視圖應(yīng)用樣式

為 XML 布局中的視圖設(shè)置樣式的方法如下:

<TextView
    style="@style/CodeFont"
    android:text="@string/hello" />

現(xiàn)在該 TextView 將按照名為 CodeFont 的樣式的定義設(shè)置樣式(請(qǐng)參閱上文定義樣式中的示例)。

2)對(duì) Activity 或應(yīng)用應(yīng)用主題

要為您的應(yīng)用的所有 Activity 設(shè)置主題,請(qǐng)打開(kāi) AndroidManifest.xml 文件并編輯 <application> 標(biāo)記,在其中加入帶樣式名稱的 android:theme 屬性。 例如:

<application android:theme="@style/CustomTheme">

如果您只想對(duì)應(yīng)用中的一個(gè) Activity 應(yīng)用主題,則改為給 <activity> 標(biāo)記添加 android:theme 屬性。
正如 Android 提供了其他內(nèi)建資源一樣,有許多預(yù)定義主題可供您使用,可免于自行編寫(xiě)。 例如,您可以使用 Dialog 主題,為您的 Activity 賦予類似對(duì)話框的外觀:

<activity android:theme="@android:style/Theme.Dialog">

或者,如果您希望背景是透明的,則可使用 Translucent 主題:

<activity android:theme="@android:style/Theme.Translucent">

如果您喜歡某個(gè)主題,但想做些調(diào)整,只需將該主題添加為您的自定義主題的 parent。 例如,您可以像下面這樣對(duì)傳統(tǒng)明亮主題進(jìn)行修改,使用您自己的顏色:

<color name="custom_theme_color">#b0b0ff</color>
<style name="CustomTheme" parent="android:Theme.Light">
    <item name="android:windowBackground">@color/custom_theme_color</item>
    <item name="android:colorBackground">@color/custom_theme_color</item>
</style>

(請(qǐng)注意,此處顏色需要以單獨(dú)資源形式提供,因?yàn)?android:windowBackground 屬性僅支持對(duì)另一資源的引用;不同于 android:colorBackground,無(wú)法為其提供顏色字面量。)
現(xiàn)在,在 Android 清單內(nèi)使用 CustomTheme 替代 Theme.Light:

<activity android:theme="@style/CustomTheme">

3)根據(jù)平臺(tái)版本選擇主題

新版本的 Android 可為應(yīng)用提供更多主題,您可能希望在這些平臺(tái)上運(yùn)行時(shí)可以使用這些新增主題,同時(shí)仍可兼容舊版本。 您可以通過(guò)自定義主題來(lái)實(shí)現(xiàn)這一目的,該主題根據(jù)平臺(tái)版本利用資源選擇在不同父主題之間切換。
例如,以下這個(gè)聲明所對(duì)應(yīng)的自定義主題就是標(biāo)準(zhǔn)的平臺(tái)默認(rèn)明亮主題。 它位于 res/values 之下的一個(gè) XML 文件(通常是 res/values/styles.xml)中:

<style name="LightThemeSelector" parent="android:Theme.Light">
    ...
</style>

為了讓該主題在應(yīng)用運(yùn)行在 Android 3.0(API 級(jí)別 11)或更高版本系統(tǒng)上時(shí)使用更新的全息主題,您可以在 res/values-v11 下的 XML 文件中加入一個(gè)替代主題聲明,但將父主題設(shè)置為全息主題:

<style name="LightThemeSelector" parent="android:Theme.Holo.Light">
    ...
</style>

現(xiàn)在像您使用任何其他主題那樣使用該主題,您的應(yīng)用將在其運(yùn)行于 Android 3.0 或更高版本的系統(tǒng)上時(shí)自動(dòng)切換到全息主題。
R.styleable.Theme 提供了可在主題中使用的標(biāo)準(zhǔn)屬性的列表。

簡(jiǎn)單來(lái)說(shuō):

(1) 對(duì)View使用樣式,只需要在使用View的xml布局文件里的該View標(biāo)簽下使用style屬性。
(2) 對(duì)于ViewGroup使用樣式,是不會(huì)影響到ViewGroup里的其他View的樣式的,也就是說(shuō)ViewGroup里的View是不會(huì)繼承ViewGroup的樣式的。
(3) 主題里定義的樣式是會(huì)應(yīng)用到Activity 或應(yīng)用內(nèi)的每個(gè) View的。
例如:
在value的style.xml定義了一個(gè)主題

image.png

在Activity里使用這個(gè)主題:


image.png

效果如下:


image.png

(4) 對(duì)于某些樣式屬性,至少使用對(duì)另一資源的引用

image.png

(5) 可以給不同Androdid版本定義不同的主題,例如默認(rèn)主題是res/value下的style.xml文件里定義名為L(zhǎng)ightThemeSelector的主題,如果我想在Android3.0(API為11)的系統(tǒng)顯示不同的主題,可以在res目錄下創(chuàng)建一個(gè)名為value-v11的文件夾,然后在里面的style.xml文件也命名一個(gè)LightThemeSelector的主題,如何根據(jù)需求使用對(duì)于的屬性。

image.png

(6) R.styleable.Theme 提供了可在主題中使用的標(biāo)準(zhǔn)屬性的列表。

image.png

4. 使用平臺(tái)樣式和主題

Android 平臺(tái)提供了龐大的樣式和主題集合,供您在應(yīng)用中使用。 您可以在 R.style 類中找到所有可用樣式的參考資料。 要使用此處所列樣式,請(qǐng)將樣式名稱中的所有下劃線替換為句點(diǎn)。 例如,您可以使用 "@android:style/Theme.NoTitleBar" 應(yīng)用 Theme_NoTitleBar 主題。
不過(guò),R.style 參考資料并不完備,未對(duì)樣式做全面說(shuō)明,因此查看這些樣式和主題的實(shí)際源代碼可讓您更清楚地了解每個(gè)樣式提供的樣式屬性。如需查看更詳實(shí)的 Android 樣式和主題參考資料,請(qǐng)參閱以下源代碼:
? Android 樣式 (styles.xml)
? Android 主題 (themes.xml)
這些文件有助于您通過(guò)示例進(jìn)行學(xué)習(xí)。例如,在 Android 主題源代碼中,您可以找到 <style name="Theme.Dialog">的聲明。 在該定義中,您可以看到用來(lái)為 Android 框架使用的對(duì)話框設(shè)置樣式的所有屬性。
如需了解有關(guān) XML 中樣式和主題語(yǔ)法的詳細(xì)信息,請(qǐng)參閱樣式資源文檔。
如需查看您可用來(lái)定義樣式或主題的可用樣式屬性(例如“windowBackground”或“textAppearance”)的參考資料,請(qǐng)參閱 R.attr 或您創(chuàng)建的樣式所對(duì)應(yīng)的 View 類。
這里沒(méi)什么好說(shuō)的,這段告訴我們可以到哪去查看系統(tǒng)提供給我們的樣式和主題。其實(shí)也挺重要的,我們可以查看我們使用的主題,看看哪些屬性影響到我們的控件樣式,然后就可以自定義我們的樣式覆蓋掉系統(tǒng)的樣式。

6. 參考文章

https://developer.android.com/guide/topics/ui/themes.html?hl=zh-cn

7.源碼地址

https://download.csdn.net/download/lgywsdy/11220640

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Application 標(biāo)簽 android:allowTaskReparenting android:allow...
    Shawn_Dut閱讀 7,909評(píng)論 2 61
  • 樣式和主題(Styles and Themes) 一個(gè)樣式(Style)是一個(gè)包含了指定樣子和格式的作用于視圖控件...
    張?jiān)骑wVir閱讀 2,856評(píng)論 0 51
  • R.style https://developer.android.com/reference/android/R...
    _春夏秋冬閱讀 613評(píng)論 0 0
  • 我那天回家,問(wèn)我媽要我小時(shí)候的照片,我媽找了半天,說(shuō)你小時(shí)候沒(méi)有多少照片兒。找出來(lái)的那些我看了看,哪一張都不喜歡,...
    石榴寶寶閱讀 583評(píng)論 4 7
  • 奶奶離世已14年,常常認(rèn)為她并沒(méi)有離開(kāi)我。有時(shí)傷心哭泣時(shí)會(huì)想,她應(yīng)該在天上看著我,一定不希望我不堅(jiān)強(qiáng)。今天突然想到...
    穿堂風(fēng)Mia閱讀 171評(píng)論 0 0