Android 樣式系統 | 主題背景屬性

2021-02-14 谷歌開發者

在 Android 樣式系統系列的前幾篇文章中,我們介紹了主題背景與樣式的區別,以及為什麼說通過主題背景和公共主題背景屬性來分解您要實現的內容是一個不錯的主意,請點擊連結回顧:

這會讓我們通過創建更少的布局或樣式,以隔離主題背景中的修改。在實際開發中,您通常希望根據主題背景改變顏色,因此您應該始終通過主題背景屬性來引用顏色。這意味著您可以將如下代碼視為有代碼異味 (Code smell):
<View …  android:background="@color/white"/>

相反,您應該使用主題背景屬性,它允許您按主題更改顏色,例如,在深色主題中提供一個不同的值:
<View …  android:background="?attr/colorSurface"/>

https://developer.android.google.cn/guide/topics/ui/look-and-feel/darktheme

即使您當前不支持其他主題 (什麼,您的應用還沒有支持深色主題?),我們依然建議您採用這種方法,因為這樣會讓新主題的採用變得更加簡單。

您可以通過在不同的配置中添加不同的值來改變顏色 (例如,在 res/values/colors.xml 中和在 res/values-night/colors.xml 中的備選值裡均定義 @color/foo),但我們依然建議您使用主題背景屬性來替代它們。對顏色層級的區分,會迫使您給顏色賦予語義化名稱,換句話說,您應該不會在給顏色命名為 @color/white 的同時,又為深色模式提供一個深色變體,這會讓人感到非常困惑。所以,您可能會想要使用一個語義化名稱,例如 @color/background。這種方法帶來的問題是它合併了顏色聲明和具體的值,因此,它並沒有指出顏色是可以或者能夠隨主題背景而變化的。@colors 的變化也會鼓勵您創造更多顏色。如果在不同的情境下要使用具有相同值的、新的語義化命名的顏色 (即,不是背景色但應該使用相同顏色),這時候您仍需要在 colors 文件中創建新的條目。通過使用主題背景屬性,我們可以將語義顏色的聲明從提供它們的值中區分開來,而且讓使用方更清楚地了解到顏色會隨主題背景而變化 (因為它們使用 ?attr/ 語法)。將顏色聲明保持為字面值,您就可以自定義應用使用的顏色調色板,並在主題背景級別修改它們,這會讓 color.xml 較小且易維護。這種方法的額外好處是,布局/樣式引用這些顏色時復用性變得更高。由於主題背景可以被覆蓋或者改變,因此這間接表示: 您不需要創建其他布局或樣式就可以更改某些顏色——您可以在相同的布局中使用不同的主題背景。在某些情況下,您或許不想按照主題背景更改顏色。例如,在 Material Design 規範文檔中提到,您可能希望在淺色和深色主題中均使用同一類型的顏色。
https://material.io/design/color/dark-theme.html#ui-application在這種特殊情況下,直接引用顏色資源是再合適不過的:
<FloatingActionButton …  app:backgroundTint="@color/owl_pink_500"/>

當使用 ColorStateLists 時,您可能也不會在您的布局/樣式中直接引用主題背景屬性。
<View …  android:background="@color/primary_20"/>

https://developer.android.google.cn/reference/android/content/res/ColorStateList如果 primary_20 是一個 ColorStateList,它本身引用主題背景屬性來獲取色值也可能是合理的 (請參見下文)。ColorStateLists 通常為不同的狀態 (按下,禁用等) 提供不同的顏色,但它還有另外一種可用於主題化功能您可在選取的顏色上指定透明度值:
<!-- Copyright 2019 Google LLC.     SPDX-License-Identifier: Apache-2.0 --><selector …  <item android:alpha="0.20" android:color="?attr/colorPrimary" /></selector>

這種單項 ColorStateList (即只提供單個默認顏色,而非每種狀態的不同顏色) 有助於減少您需要維護的顏色資源數量。它並沒有定義一個新的顏色資源的方式來手動為您 (每一個配置文件) 的 primary 顏色設置 alpha 值,而是通過改變當前主題背景中的 colorPrimary 的方式。如果您的原始顏色發生了變化,則只需要在一個地方進行更新,無需調整所有已更新的地方。

 

1. 如果指定的顏色也具有 alpha 值,則 alpha 會被合併。例如,將 50% 的 alpha 應用於 50% 的不透明白色中,將產生 25% 的白色:

<!-- Copyright 2019 Google LLC.     SPDX-License-Identifier: Apache-2.0 --><selector …  <item android:alpha="0.50" android:color="#80ffffff" /></selector>

因此,最好將主題背景顏色指定為完全不透明,然後使用 ColorStateLists 修改它們的 alpha。2. 僅在 API 23 中添加了 alpha 組件,因此,如果您的最小 sdk 低於這個版本,請確保使用支持此行為的 AppCompatResources.getColorStateList (並始終使用 android:alpha 命名空間,而絕不使用 app:alpha 命名空間)。AppCompatResources.getColorStateListhttps://developer.android.google.cn/reference/androidx/appcompat/content/res/AppCompatResources.html#getColorStateList(android.content.Context,%20int)3. 通常,我們使用簡寫法,將顏色設置為 Drawable,例如:
<View …  android:background="@color/foo"/>

View 的背景是一個 Drawable,此簡寫把給定的顏色強轉成了一個 ColorDrawable。但是沒有辦法把 ColorStateList 轉換成 Drawable (API 29 之前使用 ColorStateListDrawable 解決這個問題)。https://developer.android.google.cn/reference/android/graphics/drawable/ColorDrawablehttps://developer.android.google.cn/reference/android/graphics/drawable/ColorStateListDrawable

 

<View …  android:background="@drawable/a_solid_white_rectangle_shape_drawable"  app:backgroundTint="@color/some_color_state_list"/>

請確保您的 backgroundTint 支持您的 View 所需的狀態,例如,如果被禁用時需要更改。即使您已經說服自己使用主題背景屬性和 ColorStateList,但如何在代碼庫或者團隊中使用呢?您可以在 Code review 期間嘗試保持警惕,但它的擴展性不是很好。更好的方法是依靠工具來解決此問題。
《Making Android Lint Theme Aware》這篇文章簡述了如何通過添加 Lint 檢查來尋找直接引用顏色的用法,並涵蓋了文中提及到的所有建議。使用主題背景屬性和 ColorStateList 將顏色分解為主題背景的方法,可使您的布局和樣式更加靈活,提高代碼復用性並保持代碼庫的精簡和易維護性。我們將在後續文章中介紹更多主題背景的用法以及它們之間的相互影響,感興趣的讀者請繼續關注。 點擊屏末  | 了解更多與 Android 界面相關的內容和教程

相關焦點

  • Android開發樣式和主題背景
    樣式是一個屬性集合,用於指定單個 View 的外觀。 樣式可以指定字體顏色、字號、背景顏色等屬性。主題背景是一種應用於整個應用、Activity 或視圖層次結構的樣式,而不僅僅應用於單個視圖。當您將樣式作為主題背景來應用時,應用或 Activity 中的每個視圖都會應用其支持的每個樣式屬性。主題背景還可以將樣式應用於非視圖元素,例如狀態欄和窗口背景。
  • Android 字體修改,所有的細節都在這裡 | 開篇
    接下來看看當我們想要使用 Android 內置的一些字體的時候,我們需要使用哪些屬性。三、哪些屬性可以影響字體Android 本身已經提供了一些修改字體樣式的屬性和方法。android:textStyleandroid:typefaceandroid:fontFamily下面來分別詳細的說明這幾個屬性
  • Android 屬性動畫
    屬性動畫要求動畫作用的對象提供該屬性的 set 方法,屬性動畫根據傳遞的該屬性的初始值和最終值,以動畫的效果多次去調用 set 方法。每次傳遞給 set 方法的值都不一樣,確切來說是隨著時間的推移,所傳遞的值越來越接近最終值。如果動畫的時候沒有傳遞初始值,那麼還要提供 get 方法,因為系統要去獲取屬性的初始值。
  • 是時候讓 Android Tools 屬性拯救你了
    >大家肯定平時都會見到 tools:context=".XXXActivity 這個系統默認為我們生成的配置。://schemas.android.com/tools" >這些工具屬性大概可以分為以下三類:Error handling attributes即錯誤和警告處理屬性。
  • Android Studio 4.1終於發布了!
    https://youtu.be/Yhbr6u7f3ME現在,create New Project 對話框中的 Android Studio 模板使用 Material Design Components(MDC),並且默認遵循更新的主題和樣式指南。這些更改將使用戶更容易使用推薦的 material 樣式模式,並支持深色主題等現代 UI 特性。
  • 解謎:為何用了9-Patch背景圖後自帶Padding屬性?
    本次分享的主題源於筆者在實際開發中遇到的問題。具體現象為:當普通的9-Patch圖用作TextView的backGround屬性後,整個TextView便有了一定的Padding值。但筆者並沒有給定padding屬性,甚至在預覽視圖中,也沒有展現出padding效果。但運行起來後,便莫名其妙地有了內邊距。 我們先來看布局代碼:<?xml version="1.0" encoding="utf-8"?
  • android設置背景透明
    Android開發中,有調整背景色的要求。本文就分享一個調整Activity背景色為透明的Project本文是通過一個Button按鈕來實現更改Activity背景色的功能。工程就使用以前的吧,新增一個按鈕「變透明」Code:AndroidManifest.xml:<LinearLayout   android:layout_width="fill_parent"   android:layout_height="wrap_content"   android:gravity="center"   android:orientation="horizontal"&
  • Android仿全歷史——全沉浸時間軸實現
    顯然,它通過沉浸狀態欄、透明背景、recyclerView的自定義Item等,實現了一個很優秀的界面效果。今天,我要做的就是猜測這效果背後的實現原理,並仿製一個類似的界面正文解構且為了保持4.4以前系統正常使用,故需要三份 style 文件,即默認的values(不設置狀態欄透明)、values-v19、values-v21(解決半透明遮罩問題)>//valuse<style name="TranslucentTheme" parent="AppTheme"></style>// values-v19
  • Android面試題-機型適配,例如三星、小米、華為、魅族等
    中添加一個屬性android:fitsSystemWindows="true"方法二:是為4.4及以上添加了paddingTop去適配,添加layout覺得不好適配。Android通知欄的背景色有幾種情況,白色、暗色、暗色透明和黑色。如果生成的Bitmap帶背景色,這個背景色就很難選擇。如果選擇黑色背景,那麼在白色通知欄的機型上就很難看。因此不能完全在各個系統上面完美展示出來。如果不帶背景色,那麼字體顏色也面臨同樣的困惑。試想,如果在白色的背景上顯示白色的文字,用戶看到白茫茫一片,是什麼感受?
  • Android Studio 4.1重磅發布:支持內嵌安卓模擬器!
    https://youtu.be/Yhbr6u7f3ME現在,create New Project 對話框中的 Android Studio 模板使用 Material Design Components(MDC),並且默認遵循更新的主題和樣式指南。這些更改將使用戶更容易使用推薦的 material 樣式模式,並支持深色主題等現代 UI 特性。
  • Android使用LabelsView實現標籤列表控制項功能
    以上是LabelsView的核心代碼,LabelsView除了實現了item的測量和擺放以外,還提供了一系列的方法讓使用者可以方便設置標籤的樣式(包括標籤被選中的樣式)和標籤點擊、選中的監聽等。/apk/res-auto" android:id="@+id/labels" android:layout_width="match_parent" android:layout_height="wrap_content" app:labelBackground="@drawable/label_bg" //標籤的背景 app:labelTextColor
  • 自定義 EditText 樣式
    二、自定義EditText 背景Android中自帶的 EditText樣式比較醜,為了美化 EditText 可使用以下方法。自定義EditText 背景一、自定義EditText 圓角矩形背景自定義圓角矩形custom_edittext_background.xml <EditText
  • Android 沉浸式狀態欄攻略 讓你的狀態欄變色吧
    注意我們的主題是基於NoActionBar的,android:windowTranslucentStatus這個屬性是v19開始引入的。大體看完布局文件以後,有幾個點要特別注意:android:fitsSystemWindows這個屬性,主要是通過調整當前設置這個屬性的view的padding去為我們的status_bar留下空間。根據上面的解釋,如果你不寫,那麼狀態欄和Toolbar就會有擠一塊的感覺了,類似會這樣:
  • Android Material Design系列之FloatingActionButton和Snackbar
    所以FloatingActionButton是重寫ImageView的,所有FloatingActionButton擁有ImageView的一切屬性。FloatingActionButton顧名思義就是一個浮動按鈕。
  • Android 主題動態切換框架 Prism
    以下是添加了 prism 和 prism-viewpager 兩個庫的代碼:TextSetter(TextView textView)設置 TextView 中的文本顏色。ViewBackgroundSetter(View view)設置 View 的背景顏色。
  • Android 動畫
    img.postDelayed(runnable,i*10);        }    }Android 系統也提供了;View 動畫;只能用於  View。屬性動畫;於 Android 3.0 (API級別11)開始添加了屬性動畫。可以對任意對象的屬性進行動畫而不僅僅是 View,動畫默認時間間隔 300ms,默認幀率 10ms/幀。提供了動畫集合類(AnimatorSet),可將多個屬性動畫以組合的形式顯示出來。
  • Android主題換膚 無縫切換
    在這裡面你完全可以自己去定義去創建你所想要的View,如果在你在重寫的方法中返回null的話,就會以系統默認的方式去創建View。下面就正式開始介紹怎麼去做這個主題換膚吧。先來看看這個Demo的項目結構:
  • Android劉海屏適配全方案(華為、小米、Vivo、Oppo)
    方法一.利用fitsSystemWindows屬性當我們給最外層View設置了android:fitsSystemWindows="true"屬性後,當設置了透明狀態欄或者透明導航欄後,就會自動給View添加paddingTop或paddingBottom屬性,這樣就在屏幕上預留出了狀態欄的高度,我們的布局就不會佔用狀態欄來顯示了。
  • Android平板多屏幕適配
    Android 3.2 為 <supports-screens> 清單元素引入了新的屬性:android:requiresSmallestWidthDp:指定應用只用於最小寬度值。設定此值之後,只有設備的 smallestWidth 必須大於等於此值,才能使用該應用。
  • Android Design Support Library之TabLayout
    gt;TabLayout 屬性tabBackground:標籤頁的背景;tabMode:fixed, 固定標籤,tab均分,適合少的tab;scrollable,可滾動標籤,適合很多tab,默認fixed;tabTextColor:標籤字體顏色;tabSelectedTextColor:標籤選中字體顏色;tabIndicatorColor: