Android開發 – 樣式和主題

  • 2020 年 3 月 13 日
  • 筆記

樣式和主題(Styles and Themes)

一個樣式(Style)是一個包含了指定樣子和格式的作用於視圖控制項(View)或者窗體(Window)屬性集合。一個style可以指定很多屬性,比如 高度,填充,字體顏色,字體尺寸,背景色等。一個Style在xml資源文件中定義,並且和在xml中指定的布局區分開來。

在Android里的樣式和Web設計中的CSS共享一個相似的原理,它們允許你分離設計(Design)和內容(Content).

舉個例子,通過使用一個style,你可以讓你的布局xml像下面這樣:

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

並且,可以變成下面這樣:

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

所有關聯到style的屬性已經在布局xml中被刪除了,並且放在一個叫做「CodeFont」style中定義了。它通過一個style屬性被應用上。在下面的章節,你將會看到如何定義style。

一個主題(Theme)也是一個style,它被應用在所有的Activity或者application上,而不是個別的視圖控制項(View)(像上面的示例一樣)。當一個style被當做一個theme來應用,每一個activity或者application中的視圖控制項將應用每一個它支援的樣式屬性。比如,你可以在activity上使用相同的CodeFont樣式作為一個theme,這時Activity里的所有內部字體將會變成CodeFont樣式的字體樣式變成綠色的等寬字體。

定義一個樣式Style

為了創建一些樣式,你可以保存在你的工程下的 res/Values/ 文件夾下的一個XML文件中。XML文件的名字是隨意的,但是必須擴展名是 .xml 並且存放在 res/Values/ 文件夾下。

XML文件的根節點必須是<resources>

為你創建的每個樣式,添加一個<style>元素,並且需要一個name 屬性,它標識唯一性而且是必需的屬性。再為你的樣式屬性都添加進去,通過添加<item>元素來做,使用一個在樣式屬性里聲明的name屬性和一個value屬性,這兩個都是必需的。<item>的value屬性可以是一個關鍵字字元串,一個16進位的顏色描述,一個其他資源類型的引用,或者在其他樣式屬性中依賴的value。下面是一個簡單的示例樣式文件內容:

<?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>元素的子節點在編譯時都被轉換成一個程式資源對象。它可以通過<style>元素的name屬性的值(value)來被引用引用。這個示例樣式可以在XML布局中被引用,比如「@style/CodeFont」(像上面介紹的示例一樣)。

在<style>元素中的parent屬性是可選的並且指向一個其他樣式中的資源ID,它可以從這個樣式中繼承一些屬性。合適的話,你可以重寫(override)繼承到的屬性。

記住,一個你想在activity或者application中使用的樣式都被在XML文件中定義,並且所有的視圖控制項具有相同的樣式。一個樣式,比如上面定義的那個,可以被作為一style應用的單一的視圖控制項上或者被作為一個theme應用在全部的activity或者application上。如何應用的單一的視圖或者作為應用的主題,我們稍後討論。

繼承

在<style>中的parent屬性讓你可以指定一個你可以繼承其屬性的樣式。你可以使用這個從一個已經存在的樣式中繼承屬性,並且定義一些獨有的你需要改變或者添加的屬性。你可以繼承那些來自你已經自行創建的樣式或者或者繼承自在平台里構建好的樣式(See Using Platform Styles and Themes,下面,獲得關於繼承Android平台樣式的更多資訊)。比如,你可以繼承Android平台默認的字體樣式並且修改它,比如:

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

如果你想要繼承你自己創建的樣式,你不需要一定適用parent屬性。作為替代,可以為一個你想繼承的樣式的名字構建前綴而作為你的新的樣式的名稱,中間用「點」隔開。比如,為了創建一個樣式,比如繼承自上面的CodeFont樣式,但是讓顏色變成紅色,你可以這樣寫你的新樣式:

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

注意<style>標籤沒有parent屬性,但是,因為name屬性是以CodeFont(這是個你已經定義好的樣式)這個樣式名開始的,這個樣式從哪個樣式里繼承了所有的樣式屬性。這個樣式這裡覆蓋里android:textColor屬性,將文本改成了紅色。你可以引用這個新的樣式比如@style/CodeFont.Red

你可以繼續這樣繼承很多次,使用「點」鏈接這些名稱,比如,你可以擴展CodeFont.Red 變大一些,像下面這樣:

<style name="CodeFont.Red.Big"> <item name="android:textSize">30sp</item> </style> 這裡從CodeFont和CodeFont.Red繼承了,又添加了 android:textSize 屬性

注意:這樣的通過鏈接名稱的方式來繼承的方法,僅僅能用於你自己定義的資源文件中的樣式。你不能用於繼承Android內置的樣式。要想引用內置的樣式,比如TextAppearance,,你必須使用parent屬性。

樣式屬性

現在,你明白了如何定義一個樣式,你需要去學會 在<item>元素下什麼類型被定義的樣式屬性是可用的。你可能已經熟悉了很多已經有的,比如layout_width 和 textColor. 當然,還有很多的樣式屬性你可以使用。

尋找可以應用在指定視圖控制項上的屬性的最好的地方是 相應的類引用,它列出了所有支援的XML屬性。比如所有在表格 TextView XML attributes 中列出的屬性,都可以應用在一個樣式的定義中作用在TextView元素上(或者它的子類)。在 引用 中被列出的一個屬性叫做android:inputType的,這樣你可以再<EditText>元素中應用這個屬性,像下面這樣:

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

你可以為EditText 元素創建一個樣式,包含這個屬性,來代替上面:

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

這樣你的布局用的XML能夠這樣實現樣式:

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

這個簡單的示例看起來多做了一些工作,不過當你添加更多的樣式屬性並且把在多處可重用樣式的能力作為參考因素的話,你的付出將是值得的。

獲得所有可用樣式的屬性的引用(reference),請參閱 R.attr 引用。記住,所有的視圖控制項對象不接受所有相同的屬性,這樣你可以平常的引用圖為視圖控制項類指定支援的樣式屬性。然而,如果你為某個視圖控制項應用了一個樣式,這個樣式包含的屬性中不是都被支援的,視圖控制項將會應用那些屬性中的可被支援的並且簡單的忽略其他的。

一些樣式屬性,不被支援在視圖控制項里使用,僅僅能作為主題使用。那些樣式屬性應用在所有的窗體上,不能用在任何視圖控制項上。比如有些樣式屬性可以隱藏應用程式的標題,隱藏狀態條,或者更改窗體的背景。那些類型的樣式屬性不屬於任何視圖控制項對象。要發現更多 僅僅作用於theme主題 的屬性,查看R.attr 引用中的以windows開始的屬性。比如,windowNoTitle 和 windowBackground 屬性只能在應用於activity和application時發生作用。參閱下一章節可以獲得更多「在theme中應用樣式」的內容。

注意:在<item>元素中,不要忘記寫屬性名稱的前綴 android: ,這是一個命名空間,比如:<item name="android:inputType">.

在UI上應用樣式和主題

有兩種方式設置一個樣式:

  1. 為單個視圖控制項指定樣式,在XML布局文件中的視圖元素上添加style屬性。
  2. 為整個activity或者application指定樣式,在manifest.xml中的<activity>或者<application>節點元素中添加 android:theme 屬性。

當你為布局裡的單個控制項中應用一個樣式,你的樣式中定義的屬性都會應用在這個視圖組件中。如果你的樣式應用在一個ViewGroup中,它的所有子控制項元素將不能繼承這些樣式的屬性,只有你直接指定的那個視圖元素可以應用這些屬性。不過,你仍然可以通過主題的方式為你的應用下的所有視圖元素應用樣式。

要想應用一個主題,你必須在manifest.xml中為activity或者aplication上應用樣式。當你這麼做,每一個Activity或者aplication里的視圖元素都將應用這些樣式中它支援的屬性。比如,如果應用上面提到的CodeFont樣式在一個Activity上,這是所有的支援文本樣式屬性的視圖元素將應用它們。一些不支援這些屬性的視圖元素將忽略它們。如果一個視圖支援一部分屬性,那麼它將只應用這些屬性。

在視圖元素中應用樣式

下面演示如何在XML布局中設置一個樣式:

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

現在 TextView將具有樣式,像CodeFont定義的屬性描述的一樣。你可以參考上面的示例。

注意:樣式style 不需要使用android: 命名空間前綴。

在activity或者application中應用樣式

要想再你的所有activity或者application上使用樣式,打開 AndroidManifest.xml 並且修改<application>標籤,讓它包含 android:theme 屬性並指定一個樣式名稱,比如:

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

如果你想為你的應用中的某個activity使用樣式,那麼添加 android:theme 到你的<activity>標籤中。

Android提供了一些內置資源,你可以使用這些預先定義好的樣式,而不用自己再重新寫了。比如,你可以使用Dialog主題讓你的Activity 表現的像一個 對話框:

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

或者你想讓你的背景透明,使用 透明主題:

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

如果你喜歡主題,但是想開足馬力使用它,那麼你可以添加它到你的自定義主題中的parent屬性上繼承它。比如,你可以修改 傳統的 light theme 主題並使用你的自己的顏色,像下面這樣:

<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>

注意上面用到的顏色在其他資源中被提供,這裡,因為android:windowBackground 屬性僅僅支援其他資源的引用,不像 android:colorBackground屬性可以指定一個顏色描述文本。

現在,在你的Mnaifest文件中,可以使用 CustomTheme 代替 Theme.Light:

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

選擇一個平台支援的樣式作為基礎

Android較新的版本為應用提供了額外的可用的樣式,同時你可能想要使用它們在那些平台上運行,並且仍然和老版本保持兼容。你可以通過自定樣式做到,使用「資源選擇器"來切換不同的父主題,基於平台版本。

比如,下面是一個自定義樣式的聲明,這個樣式是個簡單的標準平台默認的 light theme主題。它可能被放置在res/valeus文件夾下的 XML文件中(經典的是在 res/values/styles.xml)。

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

當應用跑在Android 3.0(API級別11)或者更高以上時,可以讓這個樣式使用較為新一些的holo風格主題,你可以放置一個可供選擇的聲明樣式防止在res/values-v11這個文件夾下的XML文件中,但是讓這個樣式繼承自 holo風格的主題:

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

現在可以像任意其他那樣來使用這個主題,並且當跑在Android3.0以上時,你的應用程式會自動切換到holo風格的主題。

在 R.styleable.Theme. 里,可以找到一個標準的屬性列表供你使用。

關於更多的資訊,像比如主題和布局,基於平台版本或者設備配置等切換資源文件選擇,你可以閱讀 Providing Resources 。

使用平台樣式和主題

Android平台提供了很多樣式和主題,供你在應用程式中使用。在 R.style 類里你可以找到可以用的引用。為了使用這裡列出的樣式,你可以使用」點「替換所有的下劃線分割的 樣式名稱,比如,你可以通過」"@android:style/Theme.NoTitleBar".來使用 Theme_NoTitleBar 樣式。

R.style 引用,然而,不是和好的文件記錄,並且不能全面的描述樣式,那麼查看那些樣式和主題的實際的資源程式碼可以給你更好一些關於」各個被提供樣式屬性「的的理解。獲得更多關於樣式和主題的引用,你可以看下面的源程式碼:

Android Styles (styles.xml)  Android Themes (themes.xml)

那些文件將通過實例幫助你學習。比如,在Android的主題源程式碼中,你將找到一個聲明 <style name="Theme.Dialog">.在這些定義里,你將會看到所有的常常用到的 」被用於Android框架的樣式對話框的屬性「

更多關於 樣式和主題 在XML中的語法的資訊,請參閱 Style Resource 文檔。

對於 一個可用的樣式屬性的引用,你可以它使用定義一個樣式或者主題(比如"windowBackground" 或者 "textAppearance),在你創建一個樣式時你可以閱讀 R.attr 或者各自的視圖類。

本文翻譯自:https://developer.android.com/guide/topics/ui/themes.html