主題 : 換膚框架.

轉(zhuǎn)載:

ximsfei的博客地址:
http://blog.csdn.net/ximsfei

1

背景

換膚方案原理在網(wǎng)上已經(jīng)很多了, 這里不再詳細(xì)描述, 強迫癥的我總是想讓提供給別人使用的SDK盡量好用, 哪怕是給自己帶來額外的工作量, 經(jīng)過一段時間的奮斗, 實現(xiàn)了一個自我感覺良好的換膚框架.

這里主要來看看Android 源碼中”com.android.support:appcompat-v7”包的實現(xiàn), 以及源碼思想在Android-skin-support中的應(yīng)用 – 如何打造一款好用的換膚框架.

2

appcompat-v7包實現(xiàn)

首先來看一下源碼的實現(xiàn):

AppCompatActivity源碼

AppCompatActivity 將大部分生命周期委托給了AppCompatDelegate。
看下AppCompateDelegate的子類AppCompatDelegateImplV9實現(xiàn):

從這可以看出通過實現(xiàn)LayoutInflaterFactory接口來實現(xiàn)換膚至少可以支持到api 9以上。

網(wǎng)上很多換膚框架的實現(xiàn), 通過LayoutInflater.setFactory的方式, 在回調(diào)的onCreateView中解析每一個View的attrs, 判斷是否有已標(biāo)記需要換膚的屬性, 比方說background, textColor, 或者說相應(yīng)資源是否為skin_開頭等等.
然后保存到map中, 對每一個View做for循環(huán)去遍歷所有的attr, 想要對更多的屬性進行換膚, 需要Activity實現(xiàn)接口, 將需要換膚的View, 以及相應(yīng)的屬性收集到一起。
那么是不是能夠?qū)で笠环N讓使用者更方便的方式來實現(xiàn), 做一個侵入性盡量小的框架呢?

本著開發(fā)者應(yīng)有的好奇心, 深入的研究了一些v7包的實現(xiàn):
AppCompatDelegateImplV9中, 在LayoutInflaterFactory的接口方法
onCreateView 中將View的創(chuàng)建交給了AppCompatViewInflater

再來看一下AppCompatViewInflater中createView的實現(xiàn)

再看一下其中一個類AppCompatTextView的實現(xiàn)

AppCompatBackgroundHelper.Java

到這里我仿佛是發(fā)現(xiàn)了新大陸一樣興奮, 源碼中可以通過攔截View創(chuàng)建過程, 替換一些基礎(chǔ)的組件, 然后對一些特殊的屬性(eg: background, textColor) 做處理, 那我們?yōu)槭裁床荒軐⑦@種思想拿到換膚框架中來使用呢?

3

Android-skin-support換膚框架實現(xiàn)

抱著試一試不會少塊肉的心情, 開始了我的換膚框架開發(fā)之路。

先簡單講一下原理:

  1. 參照源碼實現(xiàn)在Activity onCreate中為LayoutInflater setFactory, 將View的創(chuàng)建過程交給自定義的SkinCompatViewInflater類來實現(xiàn)
  2. 重寫系統(tǒng)組件, 實現(xiàn)換膚接口, 表明該控件支持換膚, 并在View創(chuàng)建之后統(tǒng)一收集
  3. 在重寫的View中解析出需要換膚的屬性, 并保存ResId到成員變量
  4. 重寫類似setBackgroundResource方法, 解析需要換膚的屬性, 并保存變量
  5. applySkin 在切換皮膚的時候, 從皮膚資源中獲取資源

下面說一個簡單的例子(SkinCompatTextView):

  1. 實現(xiàn)SkinCompatSupportable接口 2. 在構(gòu)造方法中通過SkinCompatBackgroundHelper和SkinCompatTextHelper分別解析出background, textColor并保存 3. 重寫setBackgroundResource和setTextAppearance, 解析出對應(yīng)的資源Id, 表明該控件支持從代碼中設(shè)置資源, 且支持該資源換膚 4. 在用戶點擊切換皮膚時調(diào)用applySkin方法設(shè)置皮膚

對于其他View也一樣,復(fù)寫其換膚相關(guān)的API,統(tǒng)一對外入口為applySkin。

SkinCompatTextHelper的部分實現(xiàn):

4

開發(fā)過程中遇到的一些問題

在5.0以上, 使用color為ImageView設(shè)置src, 可以通過getColorStateList獲取資源, 而在5.0以下, 需要通過ColorDrawable setColor的方式實現(xiàn)

還有很多問題, 有興趣的同學(xué)可以來一起交流解決.

5

總結(jié)

這樣的做法與網(wǎng)上其他框架相比優(yōu)勢在哪里, 為什么重復(fù)造輪子?

在增加框架開發(fā)成本的基礎(chǔ)上降低了框架使用的成本, 我覺得更有意義, 一次開發(fā), 所有Android 開發(fā)者都受用;

換膚框架對業(yè)務(wù)代碼的侵入性比較小, 業(yè)務(wù)代碼只需要繼承自SkinCompatActivity, 不需要實現(xiàn)接口重寫方法, 不需要其他額外的代碼, 接入方便, 假如將來不想再使用本框架, 只需要把SkinCompatActivity改為原生Activity即可;

深入源碼, 和源碼實現(xiàn)方式類似, 兼容性更好.

為什么選擇繼承自AppCompatActivity, AppCompatTextView…而不是選擇直接繼承自Activity, TextView…

本身appcompat-v7包是一個support包, 兼容原生控件, 同時符合Material design, 我們只需要獲取我們想要換膚的屬性就可以在不破壞support包屬性的前提下進行換膚;

參與開發(fā)的同學(xué)更多的話, 完全可以支持一套繼承自Activity, TextView…的skin support包.

自定義View能否支持, 第三方控件是否支持換膚

答案是肯定的, 完全可以參照SkinCompatTextView的實現(xiàn), 自己去實現(xiàn)自定義控件, 對于使用者來說, 擴展性很好.

開源地址:
https://github.com/ximsfei/Android-skin-support

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容