一個app多主題架構完全分析

來源:互聯網
上載者:User

標籤:

ScoopsDemo

多主題風格代碼demo
本文屬代碼GG原創,非經本人同意,禁止轉載。

需要交流,聯絡:code_gg_boy
更多精彩,時時關注公眾號code_gg_home


基本用法
  • 簡要說明

     Scoops是一個android應用庫,主要解決的是多主題實現方案。通過配置多個R.style.Theme ,代碼進行動態設定主題,重啟當前介面實現。

  • 原理分析

     主要通過設定主題(儲存設定值), 重啟activity,通過setTheme方式設定style實現。

  • 使用方法

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多主題架構完全分析

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.