本章主要講了如何使用樣式與主題(style and theme),使應(yīng)用界面統(tǒng)一化標(biāo)準(zhǔn)化。
GitHub 地址:
完成第20章
1. 樣式(Style)
1.1 樣式的定義
樣式是一組能應(yīng)用于視圖組件的屬性,用于復(fù)用相同的 UI 特性
例如我們?cè)?res/values/style.xml 中定義一個(gè)樣式:
<style name="BeatBoxButton">
<item name="android:background">@color/dark_blue</item>
<!--其中的 color 資源在 colors.xml 中定義-->
</style>
那么使用這個(gè)樣式的組件就會(huì)自動(dòng)套用這個(gè)屬性:
<Button
……
style="@style/BeatBoxButton"
<!--這樣就能自動(dòng)套用這個(gè)背景的顏色-->
……/>
1.2 樣式的繼承
樣式的繼承可以在原有樣式的基礎(chǔ)上添加和覆蓋屬性
-
繼承方式一:通過命名表示樣式繼承關(guān)系
<!--用點(diǎn)連接表示繼承關(guān)系败京,只能在包內(nèi)使用--> <style name="BeatBoxButton.Strong"> <item name="android:textStyle">bold</item> </style>
-
繼承方式二:用指定父樣式的方法繼承
<!--用 parent 屬性表示繼承關(guān)系,可以跨庫(kù)使用--> <style name="StrongBeatBoxButton" parent="@style/BeatBoxButton"> <item name="android:textStyle">bold</item> </style>
2. 主題(Theme)
樣式能讓一些屬性復(fù)用,看上去節(jié)省了許多工作揍庄,在 styles.xml 公共文件中,可以為所有組件定義一套樣式屬性共用东抹。然而蚂子,如果組件多了,需要逐個(gè)為所有組件添加它們要用到的樣式缭黔,工作量是很大的食茎。
這個(gè)時(shí)候主題就可以派上用場(chǎng)了×蠼鳎可以把主題看作樣式的進(jìn)化加強(qiáng)版别渔,同樣是定義一套公共主題屬性,樣式屬性需要逐個(gè)添加惧互,而主題屬性則會(huì)自動(dòng)應(yīng)用于整個(gè)應(yīng)用哎媚。主題屬性能引用顏色這樣的外部資源,也能引用其他樣式喊儡。使用主題拨与,可以簡(jiǎn)單地說:“所有按鈕都使用這個(gè)樣式」芟”再也不用找到每個(gè)按鈕截珍,告訴它們要用哪個(gè)主題了。
2.1 主題屬性的更改
主題作用于某個(gè) activity 或者整個(gè)應(yīng)用箩朴,這和主題在 manifest 文件中的聲明位置有關(guān)岗喉,如果在 <application>
標(biāo)簽中聲明,則是作用于整個(gè)應(yīng)用炸庞,在<activity>
標(biāo)簽中聲明钱床,則是作用于單個(gè) activity。
在 manifest 文件中我們看到整個(gè)應(yīng)用的主題是android:theme="@style/AppTheme"
埠居,按住 Command(Windows 下是 Ctrl)查牌,點(diǎn)擊 AppTheme 就可以進(jìn)入其聲明的位置,可以看到以下代碼:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
</style>
AppCompat 庫(kù)自帶三大主題:
- Theme.AppCompat——深色主題
- Theme.AppCompat.Light——淺色主題
- Theme.AppCompat.Light.DarkActionBar——帶深色工具欄的淺色主題
我們把 AppTheme 的父主題修改為 Theme.AppCompat滥壕,以便于修改屬性纸颜。
2.1.1 修改主題顏色
在空空的主題 style 標(biāo)簽中加入幾個(gè)屬性,如下:
<style name="AppTheme" parent="Theme.AppCompat">
<item name="colorPrimary">@color/red</item>
<item name="colorPrimaryDark">@color/dark_red</item>
<item name="colorAccent">@color/gray</item>
</style>
- colorPrimary 屬性主要用來(lái)設(shè)置工具欄背景色绎橘。由于應(yīng)用名稱是顯示在工具欄上的胁孙,colorPrimary 也可以稱為應(yīng)用品牌色
- colorPrimaryDark 用于屏幕頂部的狀態(tài)欄。從名字可以看出,它是深色版 colorPrimary涮较。 注意稠鼻,只有 Lollipop 以后的系統(tǒng)支持狀態(tài)欄主題色。對(duì)于之前的系統(tǒng)狂票,無(wú)論指定什么主題色候齿,狀態(tài)欄都是不變的黑底色。
- 最后闺属,將 colorAccent 設(shè)置為灰色的慌盯。這個(gè)主題色應(yīng)該和 colorPrimary 形成反差效果,主要用于給 EditText 這樣的組件著色屋剑。
2.2 主題的抽絲剝繭
完成了主題配色润匙,我們繼續(xù)來(lái)點(diǎn)深入的诗眨,比如可以看看可以覆蓋的主題屬性都有哪些唉匾。在研究諸如有哪些主題屬性可用,哪些能覆蓋匠楚,甚至是有某些屬性究竟有什么作用等這樣的問題時(shí)巍膘,幾乎沒有官方參考文檔可以參考,所以要逐級(jí)往上查看芋簿。
例如峡懈,我想找到設(shè)置頁(yè)面背景顏色的屬性(隨著時(shí)間的推移,主題繼承關(guān)系和層次可能有變与斤,但下面介紹的方法不會(huì)變肪康。 想要知道該覆蓋哪個(gè)屬性,就沿著繼承樹找吧!):
第一層
也就是 AppTheme 主題撩穿,它原本是個(gè) Android Studio 自動(dòng)生成的空的主題磷支。
為什么要生成一個(gè)空主題,而不在 manifest 中直接使用
Theme.AppCompat.Light.DarkActionBar
呢食寡?這就是設(shè)計(jì)模式的事情了雾狈,對(duì)于應(yīng)用本身來(lái)說,使用的主題不管父主題是誰(shuí)抵皱,引用的都是 AppTheme 這個(gè)主題善榛,相當(dāng)于定義主題的時(shí)候留出了一個(gè) AppTheme 的接口。對(duì)于協(xié)作開發(fā)來(lái)說呻畸,你不用管我內(nèi)部如何實(shí)現(xiàn)也不用操心該怎么引用移盆,只要使用 AppTheme 就夠了。
我們繼續(xù)往上找伤为。
第二層
進(jìn)入 Theme.AppCompat
咒循,可以看到其也是一個(gè)空主題:
<style name="Theme.AppCompat" parent="Base.Theme.AppCompat"/>
要進(jìn)入上一層時(shí),可以看到有好幾個(gè)候選的父主題,這里我們選擇 values-v21 目錄下的父主題
第三層
這一層仍然是空主題
<style name="Base.Theme.AppCompat" parent="Base.V21.Theme.AppCompat"/>
那就再往上走
第四層
終于出現(xiàn)了很多屬性
<style name="Base.V21.Theme.AppCompat" parent="Base.V7.Theme.AppCompat">
……
</style>
但是沒有我們想要的設(shè)置背景的屬性剑鞍,所以要繼續(xù)往上
第五層
也定義了很多屬性昨凡,但是也沒有需要的
<style name="Base.V7.Theme.AppCompat" parent="Platform.AppCompat">
……
</style>
繼續(xù)往上,這里 Platform.AppCompat
也有多個(gè)版本蚁署,我們選擇 values-v11 下的父主題
第六層
空主題便脊,繼續(xù)往上
<style name="Platform.AppCompat" parent="Platform.V11.AppCompat"/>
第七層
終于看到了我們想要的屬性:
<!--可以看到這個(gè)主題的 parent 是帶有 android 命名空間的,表示其來(lái)源于 Android 系統(tǒng)-->
<style name="Platform.V11.AppCompat" parent="android:Theme.Holo">
……
<!-- Window colors -->
……
<item name="android:colorBackground">@color/background_material_dark</item>
……
</style>
所以光戈,最后我們可以在 AppTheme 中覆蓋這個(gè)屬性哪痰,設(shè)置背景顏色:
<item name="colorBackground">@color/soothing_blue</item>
2.3 修改按鈕顏色
同樣的饺律,我們?cè)偻险也阶觯茉?android:Theme.Holo
中找到 buttonStyle 屬性:
<item name="buttonStyle">@style/Widget.Holo.Button</item>
這樣,我們的 BeatBoxButton 可以繼承 Widget.Holo.Button
這個(gè)樣式功炮,然后在 AppTheme 中使用 buttonStyle 屬性筷弦。
3. 引用主題屬性
在主題中定義好屬性后肋演,可以在 XML 或代碼中直接使用它們。
在 XML 中引用具體值時(shí)(如顏色值)烂琴,我們使用@符號(hào)爹殊。比如 @color/gray 指向某個(gè)特定資源。
在主題中引用資源時(shí)奸绷,我們使用?符號(hào)梗夸。
比如:
<Button xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/list_item_sound_button"
android:layout_width="match_parent"
android:layout_height="120dp"
android:background="?attr/colorAccent"
tools:text="Sound name"/>
4. 挑戰(zhàn)練習(xí)
新建 values-v21 下的 styles.xml 文件,繼承自 Widget.Material.Button 即可
GitHub Page: kniost.github.io
簡(jiǎn)書:http://www.reibang.com/u/723da691aa42