市面上對數(shù)的App都提供換膚功能膜廊,這里暫且不講白天和夜間模式
下圖是網(wǎng)易云音樂的換膚功能
換膚其實(shí)就是替換資源(文字、顏色吼过、圖片等)
一绪商、換膚模式:
1.內(nèi)置換膚
? ??????????在Apk包中存在多種資源(圖片、顏色值)用于換膚時(shí)候切換耳璧。
? ????自由度低成箫,apk文件大? 一般用于沒有其他需求的日間/夜間模式app?
2.動態(tài)換膚
? ??????通過運(yùn)行時(shí)動態(tài)加載皮膚包
二、換膚流程
2.1 采集
2.2 如何采集
????????怎么才能拿到所有的view這才是關(guān)鍵旨枯!那么我們只能從setContentView()入手
那么問題來了setContentView()到底干了什么
查看源碼發(fā)現(xiàn)setContentView()通過LayoutInflater將xml轉(zhuǎn)換成View加載到window中
源碼三連
inflate干了什么蹬昌?
干貨來了!E矢簟T矸贰!
LayoutInflate 的核心是createViewFromTag()
View createViewFromTag(View parent, String name, Context context, AttributeSet attrs,
boolean ignoreThemeAttr) {
????????????...............
????View view;
????????if (mFactory2 !=null) {//核心View的創(chuàng)建工廠 是一個(gè)接口?
????????????????view =mFactory2.onCreateView(parent, name, context, attrs);
? ? ? ? ?}else if (mFactory !=null) {
????????????????view =mFactory.onCreateView(name, context, attrs);
? ? ? ? ?}else {
????????????view =null;
????????}????????
????????if (view ==null &&mPrivateFactory !=null) {
????????????view =mPrivateFactory.onCreateView(parent, name, context, attrs);
????????}
????????if (view ==null) {
????????????????????final Object lastContext =mConstructorArgs[0];
????????????????mConstructorArgs[0] = context;
????????????try {
????????????????if (-1 == name.indexOf('.')) {//判斷是否是自定義View
????????????????view = onCreateView(parent, name, attrs);
????????????????}else {
????????????????view = createView(name,null, attrs);
????????????}
????????}finally {
????????????????mConstructorArgs[0] = lastContext;
????????}
????????}
????????return view;
????}
通過分析上面代碼可以看出Factory2如果不為空那么就調(diào)用Factory2的方法創(chuàng)建View
否者就使用onCreateView()方法創(chuàng)建View
那么如果我們給定一個(gè)Factory那么我們就可以監(jiān)視所有的view
View設(shè)置資源文件的流程如圖所示
當(dāng)我們拿到當(dāng)前View的資源名稱時(shí)就會先去插件中的資源文件里找昆汹。
這就是換膚的原理
拿到資源文件相信剩下的大家就知道怎么玩了
代碼已經(jīng)上傳給 github明刷,歡迎大家一起討論研究
使用方式
皮膚包就是一個(gè)只有資源文件的Apk
大家可以看一下我其他文章哦