Android style & Theme 再探析(一)
你真的懂Style和Theme嗎?
Style 和 Theme 在初學Android都是被各種視訊一筆帶過,對其理解就是style可以類似html的css 可以繼承,可以各種地方直接引用做到直接管控,而theme更是一筆帶過,然而當我學到了一個android 國外的style 和 Theme課程才發現,一切並非如此......
Android Theme目前的應用情況
一般情況下,我瞭解到的和平常搜尋到的應用場景,一般情況都以處理window的標題欄和背景透明一類的內容,但我經過學習探究後才發現,我們對於這類的基礎知識過於的不重視,其實Theme配合style可以做到很好的管控我們UI,做到面板切換,日夜間模式
Android Theme配合Style解決的問題 (WHY)
-
將預設的view樣式修改為指定樣式的樣板程式碼,耗費時間卻沒有任何的技術含量,以前也會嘗試使用style或者自定義元件去解決這樣的問題,但這並不是最恰當的實現,後問筆者會闡述使用這種方式遇到的問題
-
在筆者公司UI資源緊張的情況,無法為所有app提供樣式設計;內部應用直接由開發自己處理UI樣式,導致app樣式都比較混亂
-
在以前筆者沒有重視style和Theme的配合使用,單單使用style管控UI元素,在app想實現日間模式,夜間模式,切換面板 等功能,變的異常困難。
Android Theme 和 Style (WHAT)
首先,我們來重新看一下官方定義的概念:
style官方原文:
A style is a collection of attributes that specify the appearance for a single View. A style can specify attributes such as font color, font size, background color, and much more.
筆者渣翻譯:
style 是一個特定樣式view的屬性的集合。一個style可以定義 比如 字型 顏色尺寸 背景等等特定屬性
Theme官方原文
A theme is a type of style that's applied to an entire app, activity, or view hierarchy, not just an individual view. When you apply your style as a theme, every view in the app or activity applies each style attribute that it supports. Themes can also apply styles to non-view elements, such as the status bar and window background.
筆者渣翻譯:
Theme 是一種應用於整個application,activity或view 整個繼承結構的樣式,而不僅僅是用於單個view。當你將style應用為Theme時,application或activity中的每一個view 都會應用它支援的每個style的屬性。Theme還可以將style應用於非檢視元素,例如status bar 和背景。
而我認為也是被很多人忽略的一個非常強大功能 —— 拓展並且自定義樣式
官方原文:
When creating your own styles, you should always extend an existing style from the framework or support library so that you maintain compatibility with platform UI styles. To extend a style, specify the style you want to extend with the parent attribute. You can then override the inherited style attributes and add new ones.
即我們可以在theme中,直接定義我們所有view元件的預設樣式,這對於我們的控制元件的樣式提供了巨大的便利,且無需像style的定義那樣,需要我們去書寫備註,或者文件去說明去方便他人在多人開發中使用
實際使用展示(HOW)
針對app的Theme重寫
<resources> <!-- Base application theme.設定我們的基礎theme --> <style name="AppTheme" parent="@style/Theme.AppCompat.Light.NoActionBar"> <!-- 此處定義大於minSdk的所有android版本可以適用Theme 方便可以只需要寫一份,統一管控 --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> <style name="EhiAppTheme" parent="AppTheme"> <!-- 此處,繼承appTheme定義不同sdk版本下新增的新Theme特性,新增到不同的value下面的style中,管控不同版本下的特性 --> <!--重寫style的預設樣式--> <item name="buttonStyle">@style/ehiButton</item> <item name="android:checkboxStyle">@style/ehiCheckBox</item> </style> <!-- 部分程式碼忽略 --> <style name="ehiButton" parent="@style/Base.Widget.AppCompat.Button"> <item name="android:background">@color/colorAccent</item> <item name="android:textColor">@color/white</item> <item name="android:textAppearance">@style/Base.TextAppearance.AppCompat.Small</item> </style> <style name="ehiCheckBox" parent="@style/Base.Widget.AppCompat.CompoundButton.CheckBox"> <item name="android:background">@color/colorPrimaryDark</item> <item name="android:textColor">@color/white</item> <item name="android:textAppearance">@style/Base.TextAppearance.AppCompat.Display1</item> <item name="android:checked">true</item> </style> </resources>
使用該Theme
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/EhiAppTheme"><!--引用定義的style--> <!--部分程式碼省略--> </application>
此時當我們再次編輯我們的layout檔案時:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MDActivity"> <Button android:id="@+id/btn" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="測試按鈕" /> <CheckBox android:layout_width="match_parent" android:layout_height="wrap_content" android:text="測試複選框" /> <RadioGroup android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="測試1" /> <RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="測試1" /> </RadioGroup> </LinearLayout>
使用效果展示

主題效果展示
可以看的出我們的佈局檔案只填寫了,最基本的寬高和文字資訊,還沒有引入任何的style,便直接可以呈現此時一個預設的狀態,減少了樣板程式碼的同時,在多人開發中,其他人無需關心按鈕的你是否定義過相關樣式,也無需自己再重新定義,因為Theme使得許多view的樣式變成了“所見即所得”狀態!
再回到剛才提出的問題:
1.將預設的view樣式修改為指定樣式的樣板程式碼,耗費時間卻沒有任何的技術含量.....
此時,第一個問題已經,直接在用法示例中得到回答。
2.在筆者公司UI資源緊張的情況,無法為所有app提供樣式設計......
在有了第一個基礎上,我們就可以定義一套基礎元件的樣式面板,用於沒有UI的android的專案,這對於我們的個人開發專案同樣是一個福利,可以直接仿製或者引用他人的一套theme
3.在以前筆者沒有重視style和Theme的配合使用,單單使用style管控UI元素,在app想實現日間模式,夜間模式,切換面板 等功能,變的異常困難。
這個只需要在前面的基礎上,新增多套Theme利用java程式碼進行切換即可!
博主部落格:
http://www.whdreamblog.cn/