在現(xiàn)階段的安卓開發(fā)中谎懦,有著大量高級的開發(fā)組織架構(gòu),例如MVP溃斋,MVVM或者Clean Architecture界拦,還有些瘋狂點(diǎn)的例如RxJava或者Dagger,甚至還有新語言出現(xiàn)梗劫,比如Kotlin享甸。
但是在大多數(shù)項(xiàng)目中,主題和樣式仍然是使用了最老式的方法梳侨,并沒有考慮其組織結(jié)構(gòu)蛉威。但是這些xml文件也是項(xiàng)目代碼的一部分问慎,所以展示它們也應(yīng)該像展示我們喜歡的Java代碼一樣滞伟。
一個常見問題
在一個新項(xiàng)目里雅宾,AS只會生成一個sytle.xml文件莹痢,里面有個初期的AppTheme的實(shí)現(xiàn)摩钙。當(dāng)你的項(xiàng)目慢慢變大麻汰,AppTheme也將會變大庐冯,里面將會放著很多你的主題/樣式屬性吐绵。
但是彼哼,在你項(xiàng)目的某些點(diǎn)上对妄,你可能需要添加一些API級別的特殊樣式屬性。例如敢朱,你的app的minSdk=16剪菱,但是你想要一個API19級別屬性摩瞎,這時你不能直接放到AppTheme 中了,否則xml文件將會報(bào)錯孝常。見圖
在安卓中旗们,你可以將一些資源文件放到特定API級別的文件夾中。例如构灸,你可以創(chuàng)建一個 res/values-v19/文件夾上渴,并且你可以向里面放入一個style.xml文件,當(dāng)項(xiàng)目運(yùn)行在一個API19甚至更高級別的設(shè)備上時喜颁,本文件具有更高的優(yōu)先級稠氮。由此,為引入API 19級別的新屬性半开,你有了2個簡單方式隔披。
- .將res/values/styles.xml中的AppTheme 復(fù)制到-v19的style文件中,然后向新文件中添加新屬性寂拆。此時奢米,-v19 將會只應(yīng)用在API 19級別以及更高的設(shè)備。但是漓库,請不要這么做恃慧,因?yàn)橥瑫r維持這兩個文件將會是個大麻煩,因?yàn)槊燧铮坏┠阆胂騜ase theme添加新屬性時痢士,你不得不拷貝一份放到-v19 主題中。這才一個19呢茂装,若是再考慮-v21怠蹂,-v23呢。
- 另一個方案是少态,在res/values/styles.xml中創(chuàng)建一個BaseAppTheme 城侧,里面列出所有的非指定性屬性。在同一個文件中彼妻,讓AppTheme 繼承BaseAppTheme嫌佑。在 -v19 version中,也這么操作侨歉。然后再向AppTheme中添加對于API級別的新屬性屋摇。當(dāng)以后需要添加通用屬性時,可以只改變BaseAppTheme 幽邓,而不用考慮別的文件炮温。
values/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Base application theme. -->
<style name="BaseAppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowBackground">@color/windowBackground</item>
</style>
<style name="AppTheme" parent="BaseAppTheme"/>
</resources>
values-v19/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="BaseAppTheme">
<item name="android:windowTranslucentStatus">true</item>
</style>
</resources>
更多的API級別
現(xiàn)在,你需要使用一個只有API 21級別的新屬性牵舵。你需要創(chuàng)建一個 res/values-v21/ folder柒啤,然后在里面創(chuàng)建一個style.xml文件倦挂。你創(chuàng)建AppTheme 繼承BaseAppTheme,然后將新屬性添加到這個文件中担巩。
values-v21/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="BaseAppTheme">
<item name="android:windowSharedElementEnterTransition">@android:animator/fade_in</item>
</style>
</resources>
當(dāng)app運(yùn)行到安卓4.4設(shè)備時方援,狀態(tài)欄透明。而5.0以上設(shè)備時涛癌,狀態(tài)欄不再是透明的肯骇,也就是說,此時的AppTheme 在兩個API級別下獨(dú)立運(yùn)作祖很。
引入主題繼承鏈
為修復(fù)上述問題,我們重新寫下我們所有的主題漾脂。在res/values/styles.xml中假颇,創(chuàng)建一個具有通用屬性的Base.V0.AppTheme,該主題繼承AppCompat主題骨稿。在同一個文件中笨鸡,再創(chuàng)建個AppTheme 繼承于Base.V0.AppTheme。
values/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="Base.V0.AppTheme"/>
<style name="Base.V0.AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Generic, non-specific attributes -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowBackground">@color/windowBackground</item>
</style>
</resources>
在res/values-v19/styles.xml里坦冠,創(chuàng)建一個 Base.V19.AppTheme形耗,然后將API 19的特殊屬性放進(jìn)去,該主題的父主題是Base.V0.AppTheme辙浑。在該文件中激涤,創(chuàng)建AppTheme 繼承于Base.V19.AppTheme。
values-v19/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="Base.V19.AppTheme"/>
<style name="Base.V19.AppTheme" parent="Base.V0.AppTheme">
<!-- API 19 specific attributes -->
<item name="android:windowTranslucentStatus">true</item>
</style>
</resources>
在res/values-v21/styles.xml中判呕,創(chuàng)建Base.V21.AppTheme倦踢,然后將API 21的特殊屬性放進(jìn)去,該主題的父主題是 Base.V19.AppTheme侠草。在該文件中辱挥,創(chuàng)建AppTheme 繼承于Base.V21.AppTheme。
values-v21/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="Base.V21.AppTheme"/>
<style name="Base.V21.AppTheme" parent="Base.V19.AppTheme">
<!-- API 21 specific attributes -->
<item name="android:windowSharedElementEnterTransition">@android:animator/fade_in</item>
</style>
</resources>
在這個主題架構(gòu)中边涕,對于每一個API級別晤碘,AppTheme將會具有所有API級別的屬性,并且它很容易擴(kuò)展功蜓,方便以后添加一些新的API級別特定屬性园爷。這也可以應(yīng)用到styles中,因?yàn)檫@不僅對于API級別特定屬性有效霞赫,同時對于重寫values值也適用腮介。下面舉個完整的例子,例子中有個View將會同時考慮手機(jī)和平板以及API級別21以上端衰。
values/styles.xml
提供默認(rèn)的手機(jī)屬性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Style.MainContent" parent="Base.Style.MainContent" />
<style name="Base.Style.MainContent" parent="Base.SW.Style.MainContent" />
<style name="Base.SW.Style.MainContent" parent="Base.SW0.Style.MainContent" />
<style name="Base.SW0.Style.MainContent" parent="Base.ApiLevel.Style.MainContent">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_margin">8dp</item>
</style>
<style name="Base.ApiLevel.Style.MainContent" parent="Base.V0.Style.MainContent" />
<style name="Base.V0.Style.MainContent" parent="">
<item name="android:background">#FFFFFF</item>
</style>
</resources>
values-v21/styles.xml
提供API 21+屬性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Base.ApiLevel.Style.MainContent" parent="Base.V21.Style.MainContent" />
<style name="Base.V21.Style.MainContent" parent="Base.V0.Style.MainContent">
<item name="android:elevation">4dp</item>
</style>
</resources>
values-sw600dp/styles.xml
提供平板屬性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Base.SW.Style.MainContent" parent="Base.SW600.Style.MainContent" />
<style name="Base.SW600.Style.MainContent" parent="Base.SW0.Style.MainContent">
<item name="android:layout_width">480dp</item>
<item name="android:layout_margin">0dp</item>
<item name="android:layout_gravity">center_horizontal</item>
</style>
</resources>
上述例子叠洗,每一個屬性將只會寫一次甘改,很容易維護(hù),并且也很容易擴(kuò)展灭抑。
以上就是本文展示的一個定義和組織 主題和樣式的一種方式十艾,希望對大家有幫助。