前言
最近有個換膚的需求。基于github上的這個開源框架Android-Skin-Loader。這個框架的換膚機制是使用動態加載的機制去加載皮膚包里面的內容,所謂的皮膚包是實際上是一個apk文件,里面無需任何java代碼。只要把和需要換膚的apk相同文件名的資源文件添加到res文件夾底下即可。(后面會針對怎么制作皮膚包做一個詳解)
本文提供了源代碼的下載,對急于想使用干貨的童鞋很有幫助,只要認真看完肯定就能上手。
對于這個框架的源碼分析暫不做研究,感興趣的童鞋前往此處?Android主題換膚 無縫切換。同時也感謝作者的資源分享!
好了,廢話不多bb。現在我們開始研究如何使用干貨。
1 下載基本的android-skin-loader的文件
百度網盤?提取碼: dbje?
同時也歡迎下載自己的github開源項目,里面包含了換膚等其他效果 。
2Application繼承SkinBaseApplication
3對需要使用的view添加標志
有兩種方式 1)在xml文件中添加 skin:enable="true"
2)那么有的人會有一個疑問,如果我的view是動態添加的呢?別急,作者也想到了這個需求,我們也可以動態的添加標識。
我們看下這個方法
第一個參數:需要換膚的view、第二個參數:類型名、第三個參數是資源文件id
主要是第二個參數:類型名
實際上這個是可以自定義的,關于自定義皮膚屬性下面會講。
4使用換膚功能的activity繼承SkinBaseActivity
當然如果是fragment就繼承SkinBaseFragment
5換膚
我們可以看到真正使用的是load方法,第一個參數是資源路徑,第二個參數是回調。
可以看到這里做的是本地資源保存然后我將他寫入了根目錄下。當然這里使用線上下載也是同樣的道理,相信不是什么問題。只是這里為了方便所以用了本地的,建議換膚前先下載 xxxx.skin文件到手機外存儲。
好了,大概的使用就這樣。
付加:
1此處我們對上文提到的自定義皮膚屬性進行研究。
其中我們看到既然有background那么我們是否可以對ImageView設置前景圖片src呢? ?答案是肯定的。
我們模仿他寫了一個SRC=“src".
調用get的方法
注意條件 AttfFactory.isSuppotesAttr(attrName) 這句話從字面上可以知道是匹配屬性名是否支持提供的幾個皮膚屬性。如果匹配比如:src則返回SrcAttr。
SrcAttr ?這個類是我們自定義的我們接下去看
自定義皮膚屬性總結:
原理還需要看源碼,上面的幾張圖的代碼是主要所在。
如果只看功能的實現:首先要自定義一個類繼承SkinAttr 如上圖。接著在AttrFactory的get方法中添加返回。
需要注意的是比如我的imageview設置src,一定要加上skin:eanble="true"或者動態添加。理由如下:
如上圖可看出在返回view之前做了一步篩選,如果沒有設置enable則直接過濾。
2 皮膚文件的制作
皮膚文件實際上是一個只包含了資源文件不需java代碼的pak文件
1首先創建一個新的project將和需要換膚的原apk中同名的資源文件導入。比如原apk中有一個需要換膚的textview字體顏色是@color/white 那么新的project一定要存在一個同名的資源文件至于顏色那就根據實際重新設置了。
2導出project的apk文件 改名為xxxx.skin
3將xxxx.skin文件寫入本地作為本地換膚或者扔給服務器讓他們提供一個地址下載到本地作為線上換膚,如果修改文件大的話肯定是建議后者。
bug:
目前發現的bug不多
1: 如果你的應用是全屏的,當發現在application初始化換膚設置(也就是換膚可以實行的操作)就會發現出現狀態而導致無法全屏
解決方法: 代碼研究后發現在SkinBaseActivity中有個changeStatusColor(),系統默認4.4以上都會修改狀態欄的顏色。于是把他注釋掉就可以實現全屏的需求了。
2:細心的童鞋其實還會發現一個問題,比如我一個ImageView背景是根據條件的設置的比如條件1: 背景R.drawable.icon1 ? 條件2:背景是R.drawable.icon2那現在就有一個問題了。上文提到的皮膚包設置的資源文件名字必須和原始的一樣,那這種情況我要怎么設置名字呢?
解決方法: 實際上上文也提過一個動態添加皮膚view的方式。凡是類似這種需求的都用動態添加的方式
dynamicAddSkinEnableView(View view,String attrName, intattrValueResId)
該方法包括了動態添加修改標志以及設置了設置了資源,所以無需重新設置背景或者顏色。
另外
SkinManager.getInstance.notifySkinUpdate();耗時操作,記得一定要慎用!