業(yè)務(wù)實(shí)踐心得總結(jié)
基于前幾篇的探究,我們已經(jīng)有了對(duì)一個(gè)app的theme和style的理論探究和demo描述了不少泉褐,那么接下來針對(duì)我在自己在app生產(chǎn)環(huán)境中的使用的一個(gè)使用心得總結(jié)
Android Theme的生產(chǎn)環(huán)境使用總結(jié)
本篇主要針對(duì)小伙伴如果要在自己的app中實(shí)踐赐写,整理以前混亂的theme和style的一個(gè)實(shí)踐
針對(duì)Theme配置的一些建議
如果大家按本文第一章的方式設(shè)定Theme時(shí),一定要注意幾點(diǎn):
文字顏色一定要設(shè)置小心膜赃,由于Theme具有繼承性挺邀,所以文字顏色的設(shè)定會(huì)被Android本身的style的繼承結(jié)構(gòu)沿用到其子類;但是跳座,在沿用其子類時(shí)端铛,有時(shí)會(huì)進(jìn)行一定配置的重寫,而此時(shí)重寫的配置就會(huì)變?yōu)橐粋€(gè)不可控因素疲眷,產(chǎn)生意想不到的bug
示例:
筆者在使用時(shí)禾蚕,設(shè)定了這樣的配置
<style name="ThemeBase" parent="Theme.AppCompat.Light.NoActionBar">
<!--忽略部分代碼-->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="buttonStyle">@style/EhiTheme.Button</item>
</style>
<!--主題修改為使用最新-->
<style name="EhiTheme" parent="ThemeBase">
<!--定義v21 之前api的內(nèi)容-->
</style>
<!--重寫button默認(rèn)樣式-->
<style name="EhiTheme.Button" parent="@style/Widget.AppCompat.Button">
<item name="android:background">@drawable/btn_default_ehi_selector</item>
<item name="android:textColor">@color/white</item>
</style>
代碼可以看的出,此為一個(gè)button的默認(rèn)樣式修改咪橙;而這份代碼關(guān)鍵就在于
<item name="android:textColor">@color/white</item>
這句代碼將按鈕文字設(shè)置為白色十分危險(xiǎn)夕膀,因?yàn)锳ndroid中很多控件都會(huì)沿用這部分的樣式;但是美侦,同時(shí)這個(gè)部分的樣式針對(duì)各個(gè)版本的Android系統(tǒng)上也是有著不同的體現(xiàn)产舞!
以下是不同版本下,此重寫樣式后AlertDialog的不同體現(xiàn)
通過上圖可以看到菠剩,在Android 6.0的彈窗上易猫,文字采用了colorAccent的顏色,而Android8.0則采用了文字繼承下來的白色具壮;但是兩者在顯示上的一個(gè)共同點(diǎn)就是准颓,背景都被置空;這就造成了白色背景加上白色字體的顯示bug棺妓!
a>同時(shí),要特別注意的一點(diǎn)是攘已,這樣的bug不止存在alertDialog,同樣會(huì)反映在 timePickDialog和datePickDialog上面怜跑!
b>另外样勃,需要大家注意的是吠勘,在v7包下的alertDialog和app包下的alertDialog是讀取的兩套設(shè)定
v7包:
<item name="alertDialogTheme"></item>
app系統(tǒng)包下:
<item name="android:alertDialogTheme"></item>
如果項(xiàng)目在使用上不規(guī)范的情況下,很可能兩種dialog都會(huì)引入進(jìn)行使用峡眶,那么兩種其一不起作用剧防,都會(huì)有產(chǎn)生Bug的風(fēng)險(xiǎn)!
解決方案:
針對(duì)Dialog的Theme主題部分辫樱,進(jìn)行重寫
定義Alert自己的Theme:
colors.xml
<color name="colorAccent">#FFFF7E00</color>
Themes.xml
<style name="EhiTheme.AlertDialog" parent="Theme.AppCompat.Light.Dialog.Alert">
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColor">@color/colorAccent</item>
<item name="buttonStyle">@style/EhiTheme.Button.Alert</item>
</style>
<style name="EhiTheme.Button.Alert" parent="@style/Widget.AppCompat.Button">
<item name="android:background">@color/white</item>
<item name="android:textColor">@color/colorAccent</item>
</style>
<style name="ThemeBase" parent="Theme.AppCompat.Light.NoActionBar">
<!--定義v7 之后所有api的內(nèi)容-->
<!--基本主題色-->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<!--部分忽略-->
<item name="buttonStyle">@style/EhiTheme.Button</item>
<item name="alertDialogTheme">@style/EhiTheme.AlertDialog</item>
<item name="android:alertDialogTheme">@style/EhiTheme.AlertDialog</item>
</style>
v21中Themes.xml
<style name="EhiTheme" parent="ThemeBase">
<!--定義v21 之后api的內(nèi)容-->
<item name="android:timePickerDialogTheme">?alertDialogTheme</item>
<item name="android:datePickerDialogTheme">?alertDialogTheme</item>
<item name="android:alertDialogTheme">?alertDialogTheme</item>
</style>
代碼中峭拘,如果結(jié)構(gòu)不好有多個(gè)baseActivity基類一定要注意!父類在繼承FragmentActivity和AppCompatActivity時(shí)狮暑,其展現(xiàn)形式是不一樣的鸡挠,由于AppCompatActivity在為了保證變?yōu)榻y(tǒng)一樣式在內(nèi)部做了很多封裝;(ps:theme繼承了的情況下Theme.AppCompat.Light.NoActionBar心例;使用基礎(chǔ)activity會(huì)crash)宵凌,需要在添加后測(cè)試一下
針對(duì)view自定義屬性
自定義控件的屬性的命名的一點(diǎn)小建議:
以前我們的自定義view屬性的命名全憑喜好
主流的一般有這樣的,小駝峰的命名形式
<declare-styleable name="EhiTitleBar">
<attr name="isSearchView" format="boolean"/>
<attr name="searchViewHint" format="string" />
<attr name="titleBackground" format="color|reference" />
</declare-styleable>
還有下劃線大法的
<declare-styleable name="EhiDrawingBoard">
<attr name="stroke_width" format="integer"/>
<attr name="paint_color" format="color"/>
<attr name="canvas_color" format="color|reference"/>
<attr name="anti_alias" format="boolean"/>
</declare-styleable>
但是我認(rèn)為很多內(nèi)容的使用止后,我們都應(yīng)該更接近原生控件的使用:
例如textView
<TextView
android:id="@+id/text_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="今天"
android:layout_marginLeft="10dp"
android:textColor="@color/black"
android:textSize="18sp" />
可以看的出android的控件命名其實(shí)是分成兩部分
屬性是作用于其子類本身的內(nèi)部,像這樣的文本尺寸
android:textSize="18sp"
采用了小駝峰法
而屬性比如是作用于控件的類似layoutparam這種和父類相關(guān)的屬性
android:layout_height="wrap_content"
以下劃線來區(qū)分溜腐,這樣其實(shí)我覺得對(duì)于學(xué)習(xí)和接受度其實(shí)都可以很快译株,畢竟在使用原始控件時(shí)的方式都類似
Style命名的一點(diǎn)小建議
style的使用命名規(guī)范的一點(diǎn)小建議
以前的style我們是這么命名的:
<!-- 條目標(biāo)簽樣式 -->
<style name="item_reimburse_label">
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_weight">0.3</item>
</style>
但是,這種命名其實(shí)非常凌亂挺益,
- 看不出style的層級(jí)關(guān)系歉糜,繼承關(guān)系
- 看不出它所屬的模塊;所以在比較大的項(xiàng)目工程中望众,在上方使用者調(diào)用會(huì)非撤瞬梗混亂
- style的統(tǒng)一管理十分困難,有差不多的一組style有樣式改動(dòng)烂翰,將會(huì)是一個(gè)災(zāi)難
- 組件化后夯缺,各個(gè)模塊容易出現(xiàn)命名重復(fù)問題
后來我們進(jìn)行了一點(diǎn)優(yōu)化
<!--myorder是module名-->
<style name="myorder_item_reimburse_label">
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_weight">0.3</item>
</style>
命名雖然看的出模塊所屬,但是我覺得沒有充分將style的功能發(fā)揮出來甘耿,使用也并不怎么友好踊兜!
我認(rèn)為比較適合我們?cè)诖笮晚?xiàng)目中工程化的style的命名是需要更向系統(tǒng)的style命名形式靠攏的:
一般我們可以采用大駝峰的命名形式,以 . 作為各種應(yīng)用場(chǎng)景的區(qū)分
Module.頁面.控件類型.控件修飾描述
<!--總模塊-->
<style name="CompanyInfo" />
<!--總模塊佳恬,所屬界面-->
<style name="CompanyInfo.DriverMangerSearchOrderResult" />
<!--總模塊捏境,所屬界面.對(duì)應(yīng)控件-->
<style name="CompanyInfo.DriverMangerSearchOrderResult.ItemLabelContent">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginTop">@dimen/tv_order_content_margin_top</item>
<item name="android:ellipsize">end</item>
</style>
<!--總模塊,所屬界面.對(duì)應(yīng)控件.控件應(yīng)用場(chǎng)景描述-->
<style name="CompanyInfo.DriverMangerSearchOrderResult.ItemLabelContent.NoBackground">
<item name="android:background">@null</item>
</style>
可是毁葱,我們很多情況下會(huì)有很多界面共用同樣的樣式垫言,所以為了這種情況,我們可以利用 style的顯示繼承
首先倾剿,定義一個(gè)公共模塊的樣式
<!--labelContentView的Style-->
<style name="EhiBase.Widget.LabelContent">
<!--部分忽略-->
<item name="contentColor">@color/colorGray100</item>
<item name="contentHintColor">@color/colorGray350</item>
</style>
然后筷频,在自己的module里面直接進(jìn)行引用,這樣,在同時(shí)保證了命名的統(tǒng)一的同時(shí),還兼顧的使用通用樣式
<!--用于個(gè)人管理模塊-->
<style name="PersonalManager" />
<!--個(gè)人信息界面-->
<style name="PersonalManager.MyInformation" />
<!--利用顯示繼承截驮,使用通用樣式-->
<style name="PersonalManager.MyInformation.LabelContent" parent="EhiBase.Widget.LabelContent"/>
這樣有以下優(yōu)勢(shì)
- 有統(tǒng)一的模塊描述笑陈,頁面描述,控件描述葵袭;
- 能夠更好使得命名空間不沖突
- 同時(shí)利用 style的顯式繼承可以做到對(duì)控件的統(tǒng)一管控
- 類似Android原生的用法涵妥,上手更快
部分源碼展示
<style name="Theme.AppCompat" parent="Base.Theme.AppCompat"/>
<style name="Theme.AppCompat.CompactMenu" parent="Base.Theme.AppCompat.CompactMenu"/>
<style name="Theme.AppCompat.DayNight" parent="Theme.AppCompat.Light"/>
<style name="Theme.AppCompat.DayNight.DarkActionBar" parent="Theme.AppCompat.Light.DarkActionBar"/>
<style name="Theme.AppCompat.DayNight.Dialog" parent="Theme.AppCompat.Light.Dialog"/>
<style name="Theme.AppCompat.DayNight.Dialog.Alert" parent="Theme.AppCompat.Light.Dialog.Alert"/>
隱式繼承控制命名的完整性,顯式繼承控制模塊與模塊之間的通用部分
專題系列:
Android style & Theme 再探析(一)—— 你真的懂Style和Theme嗎坡锡?
Android style & Theme 再探析(二) —— 一統(tǒng)View規(guī)范的大殺器——material design
Android style & Theme 再探析(三) —— 定制Theme示例和日夜間模式踩坑大匯總
Android style & Theme 再探析(四) —— 業(yè)務(wù)實(shí)踐心得總結(jié)
博主博客:
http://www.whdreamblog.cn/