樣式與主題

嘗試 Compose 方法
Jetpack Compose 是 Android 推薦的 UI 工具包。瞭解如何在 Compose 中使用主題設定。

Android 上的樣式和主題可讓您區分應用程式設計的詳細資料與 UI 結構和行為,與網頁設計中的樣式表類似。

「樣式」是一組屬性,可指定單一 View 的外觀。樣式可指定各種屬性,例如字型顏色、字型大小、背景顏色等。

「主題」是套用至整個應用程式、活動或檢視區塊階層 (而不只是個別檢視畫面) 的屬性集合。套用主題時,應用程式或活動中的每個檢視畫面都會套用該主題的所有支援屬性。主題也可以將樣式套用至非檢視元素,例如狀態列和視窗背景。

樣式和主題會在 res/values/樣式資源檔案中宣告,通常名為 styles.xml

圖 1 套用至相同活動的兩個主題:Theme.AppCompat (左側) 和 Theme.AppCompat.Light (右側)。

主題與樣式

主題和樣式有許多相似之處,但用途不同。主題和樣式具有相同的基本結構,也就是將屬性對應至資源的鍵/值組合。

「樣式」會指定特定檢視畫面類型的屬性。舉例來說,某個樣式可能會指定按鈕的屬性。您在樣式中指定的每個屬性都是可在版面配置檔案中設定的屬性。將所有屬性擷取至樣式,即可輕鬆使用及維護多個小工具的屬性。

「主題」會定義具名資源的集合,可供樣式、版面配置、小工具等進行參照。主題會將語意名稱 (例如 colorPrimary) 指派給 Android 資源。

樣式和主題應相輔相成。舉例來說,您可能有一個樣式指定某個按鈕的一部分為 colorPrimary,而另一個部分是 colorSecondary。這些色彩的實際定義會在主題中提供。裝置進入夜間模式時,應用程式可以從「淺色」主題切換為「深色」主題,變更所有資源名稱的值。由於樣式使用的是語意名稱,而不是特定色彩定義,因此您不需要變更樣式。

如要進一步瞭解主題和樣式如何搭配運作,請參閱網誌文章「Android 樣式設定:主題與樣式」。

建立和套用樣式

如要建立新樣式,請開啟專案的 res/values/styles.xml 檔案。針對要建立的每個樣式,請按照下列步驟操作:

  1. 新增 <style> 元素,並具備可唯一識別樣式的名稱。
  2. 為您要定義的每個樣式屬性新增 <item> 元素。每個項目中的 name 會指定您要在版面配置中做為 XML 屬性的屬性。<item> 元素中的值為該屬性的值。

例如,假設您定義了以下樣式:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="GreenText" parent="TextAppearance.AppCompat">
        <item name="android:textColor">#00FF00</item>
    </style>
</resources>

可依下列方式將樣式套用至檢視畫面:

<TextView
    style="@style/GreenText"
    ... />

如果檢視畫面接受樣式,樣式中指定的每個屬性都會套用至該檢視畫面。檢視畫面會忽略所有不接受的屬性。

不過,您通常可以按照本指南另一節的說明,針對整個應用程式、活動或檢視畫面集合,以主題形式套用樣式,而不必將樣式套用至個別檢視畫面。

擴充和自訂樣式

建立自己的樣式時,請一律從架構或支援資料庫擴充現有樣式,以維持與平台 UI 樣式的相容性。如要擴充樣式,請使用 parent 屬性指定要擴充的樣式。然後,您可以覆寫沿用的樣式屬性,並新增屬性。

舉例來說,您可以沿用 Android 平台的預設文字外觀,並按照以下方式修改:

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

不過,請一律沿用 Android 支援資料庫的核心應用程式樣式。支援資料庫中的樣式可針對各版本提供的 UI 屬性,為每個樣式進行最佳化,藉此提供相容性。支援資料庫樣式的名稱通常會與平台的樣式相似,但包含 AppCompat

如要從程式庫或自己的專案沿用樣式,請宣告父項樣式名稱,但「不要」如上述範例所示的 @android:style/ 部分。例如,以下範例會沿用支援資料庫的文字外觀樣式:

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

您也可以沿用平台的樣式 (來自平台的項目除外),方法是以點標記法擴充樣式名稱,而非使用 parent 屬性。也就是說,在樣式名稱前面加上要沿用的樣式名稱,並以半形句號分隔。通常只有在擴充專屬樣式時才會執行此操作,其他程式庫的樣式則不在此限。例如,以下樣式繼承上述範例中 GreenText 的所有樣式,然後增加文字大小:

<style name="GreenText.Large">
    <item name="android:textSize">22dp</item>
</style>

您可以鏈結更多名稱,以無限次繼續沿用這類樣式。

如要查看可使用 <item> 標記宣告的屬性,請參閱各種類別參考資料中的「XML 屬性」表格。所有檢視畫面都支援基礎 View 類別中的 XML 屬性,許多檢視畫面也會新增專屬的特殊屬性。舉例來說,TextView XML 屬性包含 android:inputType 屬性,可套用至接收輸入內容的文字檢視區塊,例如 EditText 小工具。

套用樣式做為主題

建立主題的方式與建立樣式的方式相同。但這麼做的差別在於,您不是使用 style 屬性在檢視畫面上套用樣式,而是在 AndroidManifest.xml 檔案的 <application> 標記或 <activity> 標記上套用含有 android:theme 屬性的主題。

舉例來說,以下說明如何將 Android 支援資料庫的 Material Design「深色」主題套用至整個應用程式:

<manifest ... >
    <application android:theme="@style/Theme.AppCompat" ... >
    </application>
</manifest>

將「淺色」主題套用至單一活動的方法如下:

<manifest ... >
    <application ... >
        <activity android:theme="@style/Theme.AppCompat.Light" ... >
        </activity>
    </application>
</manifest>

應用程式或活動中的每個檢視畫面都會套用其支援的樣式 (從指定主題中定義的樣式)。如果檢視畫面僅支援樣式中宣告的部分屬性,則只會套用這些屬性,並忽略不支援的屬性。

從 Android 5.0 (API 級別 21) 和 Android 支援資料庫 v22.1 版開始,您也可以將 android:theme 屬性指定至版面配置檔案中的檢視畫面。這會修改該檢視畫面和任何子檢視畫面的主題,方便您修改介面特定部分的主題調色盤。

上述範例說明如何套用 Android 支援資料庫提供的主題,例如 Theme.AppCompat。不過,您通常會希望自訂主題,以符合應用程式的品牌。最佳做法是從支援資料庫擴充這些樣式,並覆寫部分屬性,如下一節所述。

樣式階層

Android 提供多種在 Android 應用程式中設定屬性的方法。例如,您可以在版面配置中直接設定屬性、將樣式套用至檢視區塊、將主題套用至版面配置,甚至透過程式輔助方式設定屬性。

選擇如何設定應用程式的樣式時,請留意 Android 的樣式階層。一般來說,請盡可能使用主題和樣式,以維持一致性。如果您在多個位置指定相同的屬性,以下清單將決定最終套用的屬性。這份清單會依優先順序由高到低排序。

  1. 使用文字時距將字元或段落層級樣式套用至 TextView 衍生類別。
  2. 透過程式輔助方式套用屬性。
  3. 將個別屬性直接套用至檢視畫面。
  4. 將樣式套用至檢視畫面。
  5. 預設樣式。
  6. 將主題套用至一組檢視畫面、活動或整個應用程式。
  7. 套用特定檢視畫面專屬的樣式設定,例如在 TextView 上設定 TextAppearance

圖 2. 來自 span 的樣式設定會覆寫來自 textAppearance 的樣式設定。

文字外觀

樣式的其中一項限制是,您只能將一個樣式套用至 View。不過,在 TextView 中,您也可以指定 TextAppearance 屬性,其運作方式與樣式類似,如以下範例所示:

<TextView
    ...
    android:textAppearance="@android:style/TextAppearance.Material.Headline"
    android:text="This text is styled via textAppearance!" />

TextAppearance 可讓您定義文字專屬樣式,同時保留 View 的樣式供其他用途使用。不過請注意,如果您直接在 View 或樣式中定義任何文字屬性,這些值會覆寫 TextAppearance 值。

TextAppearance 支援 TextView 提供的樣式設定屬性子集。如需完整的屬性清單,請參閱 TextAppearance

部分未包含的常見 TextView 屬性為 lineHeight[Multiplier|Extra]linesbreakStrategyhyphenationFrequencyTextAppearance 適用於字元層級,而非段落層級,因此不支援影響整個版面配置的屬性。

自訂預設主題

透過 Android Studio 建立專案時,根據預設,系統會將質感設計主題套用至應用程式,如專案的 styles.xml 檔案所定義。這個 AppTheme 樣式會擴充支援資料庫的主題,並包含主要 UI 元素 (例如應用程式列懸浮動作按鈕) 使用的色彩屬性覆寫值 (如有使用)。因此,您只要更新提供的顏色,就能快速自訂應用程式的色彩設計。

例如,styles.xml 檔案看起來會像這樣:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>

樣式值實際上是在專案 res/values/colors.xml 檔案中定義的其他顏色資源的參照。亦即您編輯檔案,即可變更顏色。請參閱 Material Design 顏色總覽,瞭解如何運用動態色彩和其他自訂顏色改善使用者體驗。

確認色彩後,請更新 res/values/colors.xml 中的值:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--   Color for the app bar and other primary UI elements. -->
    <color name="colorPrimary">#3F51B5</color>

    <!--   A darker variant of the primary color, used for
           the status bar (on Android 5.0+) and contextual app bars. -->
    <color name="colorPrimaryDark">#303F9F</color>

    <!--   a secondary color for controls like checkboxes and text fields. -->
    <color name="colorAccent">#FF4081</color>
</resources>

然後視需要覆寫任何其他樣式。舉例來說,您可以按照以下方式變更活動背景顏色:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    ...
    <item name="android:windowBackground">@color/activityBackground</item>
</style>

如需可在主題中使用的屬性清單,請參閱 R.styleable.Theme 中的屬性表格。在版面配置中新增檢視畫面的樣式時,您也可以查看檢視畫面類別參考資料中的「XML 屬性」表格來尋找屬性。例如,所有檢視畫面都支援基本 View 類別中的 XML 屬性

大多數的屬性都適用於特定類型的檢視畫面,有些屬性則適用於所有檢視畫面。不過,R.styleable.Theme 中列出的部分主題屬性適用於活動視窗,而非版面配置中的檢視畫面。舉例來說,windowBackground 會變更視窗背景,windowEnterTransition 會定義活動開始時要使用的轉場動畫。詳情請參閱「使用動畫啟動活動」。

Android 支援資料庫也提供其他屬性,可用來自訂從 Theme.AppCompat 擴充的主題,例如上述範例中顯示的 colorPrimary 屬性。在程式庫的 attrs.xml 檔案中檢視這些項目時效果最佳。

支援資料庫中也有不同的主題,您可能想要擴充,而非上述範例中顯示的主題。如要查看可用主題,最好查看程式庫的 themes.xml 檔案

新增版本專屬樣式

如果新版 Android 新增要使用的主題屬性,您可以將其加入主題,同時仍與舊版相容。您只需要將另一個 styles.xml 檔案儲存在包含資源版本限定詞values 目錄中即可:

res/values/styles.xml        # themes for all versions
res/values-v21/styles.xml    # themes for API level 21+ only

由於 values/styles.xml 檔案中的樣式適用於所有版本,因此 values-v21/styles.xml 中的主題可沿用這些樣式。這表示如要避免複製樣式,您可以先從「基礎」主題開始,然後在版本專屬樣式中擴充樣式。

例如,若要宣告 Android 5.0 (API 級別 21) 以上版本的視窗轉換,您必須使用新屬性。因此,res/values/styles.xml 中的基本主題看起來會像這樣:

<resources>
    <!-- Base set of styles that apply to all versions. -->
    <style name="BaseAppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/primaryColor</item>
        <item name="colorPrimaryDark">@color/primaryTextColor</item>
        <item name="colorAccent">@color/secondaryColor</item>
    </style>

    <!-- Declare the theme name that's actually applied in the manifest file. -->
    <style name="AppTheme" parent="BaseAppTheme" />
</resources>

然後在 res/values-v21/styles.xml 中新增版本專屬樣式,如下所示:

<resources>
    <!-- extend the base theme to add styles available only with API level 21+ -->
    <style name="AppTheme" parent="BaseAppTheme">
        <item name="android:windowActivityTransitions">true</item>
        <item name="android:windowEnterTransition">@android:transition/slide_right</item>
        <item name="android:windowExitTransition">@android:transition/slide_left</item>
    </style>
</resources>

現在,您可以在資訊清單檔案中套用 AppTheme,系統會選取每個系統版本可用的樣式。

如要進一步瞭解如何針對不同裝置使用額外資源,請參閱「提供額外資源」。

自訂小工具樣式

架構和支援資料庫中的每個小工具都有預設樣式。例如,當您使用支援資料庫的主題設定應用程式的樣式時,系統會採用 Widget.AppCompat.Button 樣式來設定 Button 例項的樣式。如果想為按鈕套用不同的小工具樣式,可以在版面配置檔案中使用 style 屬性。例如,下列指令適用於程式庫的無邊框按鈕樣式:

<Button
    style="@style/Widget.AppCompat.Button.Borderless"
    ... />

如要將這個樣式套用至所有按鈕,可以在主題的 buttonStyle 中宣告,如下所示:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="buttonStyle">@style/Widget.AppCompat.Button.Borderless</item>
    ...
</style>

您也可以擴充小工具樣式,就像擴充任何其他樣式一樣,然後在版面配置或主題中套用自訂小工具樣式。

其他資源

如要進一步瞭解主題和樣式,請參閱下列其他資源:

網誌文章