標籤:
ScoopsDemo
多主題風格代碼demo
本文屬代碼GG原創,非經本人同意,禁止轉載。
需要交流,聯絡:code_gg_boy
更多精彩,時時關注公眾號code_gg_home
基本用法
1項目的build.gradle裡面
2 模組的build.gradle裡面
3 values裡面加入themes.xml
配置一些主題,為了多主題更換使用
4 AndroidManifest.xml裡面
配置上預設主題,這裡要注意的是配置的和5裡面寫的預設的那個要一致
5 MainApp裡面
完成初始化,主要設定一系列的主題。其中addToppings為的是注釋的時候使用,後面會講它的用法。setSharedPreferences 配置預設的儲存key值addDayNightFlavor 設定DayNight的主題風格,這個隨後會講到。
6 在MainAcitvity裡面
1:需要繼承AppCompatActivity
2:需要在setContentView前面調用Scoop.getInstance().apply(this);將主題設定進來。
3:這裡說下為什麼需要在AndroidManifest.xml裡面配置預設主題,因為Scoops設計,在判斷主題沒有更改的情況下,不進行設定主題,因此第一次進來不會設定。所以我們要配置預設主題。並且和MainApp裡面設定的預設值一樣。
這裡的true第三個參數說明設定為預設主題,和我們在AndroidManifest.xml設定的主題一致即可。
7 效果如下
8 代碼地址
官網 地址 https://github.com/52inc/Scoops
demo地址 https://github.com/luxiaoming/ScoopsDemo
註解用法
通過注釋方式,完成多主題的效果更換。可以減少一些代碼,使得代碼更清晰一些。
1 首先寫一個注釋類
2 在MainApp
初始化的時候,將注釋通過addToppings方式設定進去
3 在MainActivity
使用注釋@BindToppingStatus 標記下狀態列的顏色跟隨
使用注釋@BindTopping 標記下某個控制項的顏色跟隨
@BindTopping標記裡面還可以有參數
1 value對應Toppings裡面的某個值
2 adapter 跟上一個適配器,主要是為了實現某些控制項自訂的設定顏色方案
3 interpolator 可以配置顏色切換過程效果,比如AccelerateInterpolator.class
代碼可以看到還有一個注釋,叫 @BindView(R.id.fab) 這個就是之前講的Butter Knife ,不瞭解的可以在文章末尾看到地址
具體效果如下
4使用
在ButterKnife.bind(this);綁定了介面view後,使用 Scoop.sugarCone().bind(this);將view ,適配器和動畫轉場效果設定進來
在需要更新顏色的地方,使用Scoop.sugarCone().update即可,參數為第一個值為更新的注釋類型,比如Toppings.PRIMARY_DARK參數二為顏色值。
5 ColorAdapter適配器
如果需要自己自訂佈景主題更換後的view顏色變換動作(主要是有時候不符合我們的需求,比如我們想動態改文本顏色,高亮色等),我們就需要自訂一個實現ColorAdapter的類,比如ButtonColorAdapter介面 ColorAdapter定義了兩個方法
設定新的顏色值
void applyColor(T view, @ColorInt int color);
擷取使用中色彩值
int getColor(T view);
6 主題bug
1 使用 @BindTopping 注釋的時候,必須加上adapter=XXX.class 如果用預設的 ,請加上adapter = DefaultColorAdapter.class
2 預設的設定ScoopSettingsActivity介面,當設定為預設主題的時候,會出現bug。原因是這個介面指定了主題android:theme=”@style/Theme.AppCompat.Light” 如果我們預設的介面指定的跟這個不一樣,則這個設定介面則會在預設主題的時候出錯,和設定的效果不一致。解決方案:自己寫一個設定介面唄。
7 demo地址
https://github.com/luxiaoming/ScoopsDemo
Butter Knife 注釋編程閱讀地址:
http://mp.weixin.qq.com/s?__biz=MzI1MjMyOTU2Ng==&mid=2247483660&idx=1&sn=9fc37fdb8f84763896b2696c03070db0&scene=4#wechat_redirect
白天夜間主題
很多應用都有這個功能,可以選擇白天和夜間模式,給使用者更好的體驗。為此,系統也提供了一種機制,來實現此功能。
模式主要分為四種 夜間 白天 跟隨系統 和自動。具體實現可以去看com.android.support:appcompat-v7:23.0.0源碼
夜間和白天模式很好理解。自動就是根據時間判斷是否為白天和夜間,自動選擇對應主題。跟隨系統則使用系統的值,依賴系統。
實現原理
通過兩組主題,分別放在values和values-night下面,系統根據你設定的模式,對應的去找主題配置值,然後設定上去即可。
使用說明
不使用Scoops方式
1自訂一個屬性Attrs.xml
這裡可以看到定義了兩個屬性textColor和textSize 格式分別為color和dimension
2建立一個目錄values-night
3在values和values-night下面
建立一個檔案themes.xml,同時配置相同的主題,加入我們自訂的屬性textColor,給它配置值。
values下的屬性
values-night下的屬性
4使用的地方
這裡mMode的值可以取以下幾個
MODE_NIGHT_FOLLOW_SYSTEM
MODE_NIGHT_YES
MODE_NIGHT_NO
MODE_NIGHT_AUTO
5我們配置下使用的地方
這裡的 android:textColor=”?attr/textColor” 記住用的是?attr來使用自訂的屬性
6具體的結果,看Primary Color顏色變化
7代碼地址
https://github.com/luxiaoming/ScoopsDemo
使用Scoops方式
1:MainApp
使用addDayNightFlavor將一個主題設定為DayNight模式
2:在對應的主題裡面配置上文本顏色
values裡面
values-night裡面
3:進入app,在設定裡面設定成dayNight模式後,點擊按鈕Scoops方式查看效果即可。
4:效果如下
5:代碼地址
https://github.com/luxiaoming/ScoopsDemo
原理分析
核心代碼位置
https://github.com/52inc/Scoops/tree/master/scoops/src/main/java/com/ftinc/scoop可以看到主要檔案
Flavor.java 儲存每個主題資訊
Scoop.java 主檔案,主要提供介面,作為對外調用。
SugarCone.java 解析注釋的主檔案,通過使用bind方法,去反射找到編譯出來的Toppings類,通過這個來關聯上來。
Topping.java 自訂注釋方法。標記在屬性上面,然後通過編譯時間候,使用外掛程式scoops-compiler,產生尾碼為Toppings的綁定類,隨後我們使用bind函數,將這些類和介面關聯起來。
關鍵方法
Scoop.apply函數
我們來看下public void apply(Activity activity)的具體代碼流程找到當前的主題getCurrentFlavor
判斷主題是否是白天夜間模式,如果是,設定模式然後使用
另一個apply方法,參數是activity和主題id設定主題,找到設定的背景色,設定表單背景,然後返回去,我們自己recreate 重新啟動當前介面,實現切換。
編譯外掛程式
https://github.com/52inc/Scoops/tree/master/scoops-compiler
主要目的是解析我們自訂的註解。解析的主要是我們在初始化時候使用addToppings加入的我們的註解。找到後,解析出來註解的標記值,切換過場特效,和適配器。標記值的目的是更新值的時候,用這個來做區分。
代碼邏輯:找到所有的綁定在這個標記的view,然後逐個調用對應的適配器,進行對應的顏色更新。我們來看下核心的bind函數
我們看下bind 代碼,主要看下getViewBinder這個方法即可。繼續去看findViewBinderForClass 函數
代碼主要流程為:從緩衝能找到,直接返回。找不到,然後尋找Class.forName(clsName + “_ToppingBinder”)類,構造一個,然後將這個返回,並緩衝下來。然後調用裡面的bind進行關聯view我們反編譯可以看到MainActivity_ToppingBinder.smali這個smali檔案,這個就是外掛程式產生出來的代碼。我們反編譯下,看下這個檔案做了什麼。
看到了吧,將注釋的全部歸類進來,為後面更新的時候尋找使用。注釋的原理就是如此了。
一個app多主題架構完全分析