Android-換膚ThemeSkinning使用

庫(kù)源碼:https://github.com/burgessjp/ThemeSkinning
參考:https://github.com/burgessjp/MaterialDesignDemo

Demo:https://github.com/huangshuyuan/SkinDemo/

1.png

2.png

3.png

1.集成步驟:

1酪碘、添加依賴 compile 'com.solid.skin:skinlibrary:1.4.3' 參考源碼版本

2、讓你的 Application 繼承于 SkinBaseApplication

3盐茎、讓你的 Activity 繼承于 SkinBaseActivity婆跑,如果使用了 Fragment 則繼承于 SkinBaseFragment

4、在需要換膚的根布局上添加 xmlns:skin="http://schemas.android.com/android/skin"
庭呜,然后在需要換膚的View上加上skin:enable="true"

5滑进、新建一個(gè)項(xiàng)目模塊(只包含有資源文件,例如本項(xiàng)目的 skinpackage 模塊),其中包含的資源文件的 name 一定要和原項(xiàng)目中有換膚需求的 View 所使用的資源name一致募谎。

6扶关、拿到上一步生成的文件( ×××.apk ),改名為 ×××.skin数冬,放入 assets 中的 skin 目錄下( skin 目錄是自己新建的)

7节槐、調(diào)用換膚

  • 在 <code>assets/skin</code> 文件夾中的皮膚

      SkinManager.getInstance().loadSkin("Your skin file name in assets(eg:theme.skin)",
                                    new ILoaderListener() {
                                        @Override
                                        public void onStart() {
                                            Toast.makeText(getApplicationContext(), "正在切換中", Toast.LENGTH_SHORT).show();
                                        }
    
                                        @Override
                                        public void onSuccess() {
                                            Toast.makeText(getApplicationContext(), "切換成功", Toast.LENGTH_SHORT).show();
                                        }
    
                                        @Override
                                        public void onFailed() {
                                            Toast.makeText(getApplicationContext(), "切換失敗", Toast.LENGTH_SHORT).show();
                                        }
                                    }
    
                            );
    
  • 皮膚來(lái)源于網(wǎng)絡(luò)

    SkinManager.getInstance().loadSkinFromUrl(skinUrl, new ILoaderListener() {
                        @Override
                        public void onStart() {
                            Log.i("ILoaderListener", "正在切換中");
                            dialog.setContent("正在從網(wǎng)絡(luò)下載皮膚文件");
                            dialog.show();
                        }
    
                        @Override
                        public void onSuccess() {
                            Log.i("ILoaderListener", "切換成功");
                            dialog.dismiss();
                        }
    
                        @Override
                        public void onFailed(String errMsg) {
                            Log.i("ILoaderListener", "切換失敗:" + errMsg);
                            dialog.setContent("換膚失敗:" + errMsg);
                        }
    
                        @Override
                        public void onProgress(int progress) {
                            Log.i("ILoaderListener", "皮膚文件下載中:" + progress);
                            dialog.setProgress(progress);
                        }
                    });
    

詳細(xì)的使用,請(qǐng)到示例項(xiàng)目中查看

2.換膚屬性的擴(kuò)展

本開源庫(kù)默認(rèn)支持 textColor 和 background 的換膚拐纱。如果你還需要對(duì)其他屬性進(jìn)行換膚铜异,那么就需要去自定義了。

那么如何自定義呢秸架?看下面這個(gè)例子:

TabLayout大家應(yīng)該都用過(guò)吧揍庄。它下面會(huì)有一個(gè)指示器,當(dāng)我們換膚的時(shí)候也希望這個(gè)指示器的顏色也跟著更改东抹。

  • 新建一個(gè) TabLayoutIndicatorAttr 繼承于 SkinAttr蚂子,然后重寫 apply 方法。apply 方法在換膚的時(shí)候就會(huì)被調(diào)用

  • 代碼的詳細(xì)實(shí)現(xiàn)

public class TabLayoutIndicatorAttr extends SkinAttr {
    @Override
    public void apply(View view) {
        if (view instanceof TabLayout) {
            TabLayout tl = (TabLayout) view;
            if (RES_TYPE_NAME_COLOR.equals(attrValueTypeName)) {
                int color = SkinResourcesUtils.getColor(attrValueRefId);
                tl.setSelectedTabIndicatorColor(color);
            }
        }
    }
}

注:attrValueRefId:就是資源 id缭黔。SkinResourcesUtils 是用來(lái)獲取皮膚包里的資源食茎,這里設(shè)置color或者drawable一定要使用本工具類。

  • 當(dāng)上面的工作完成之后馏谨,就到我們自己的 Application 的 onCreate 方法中加入<code> SkinConfig.addSupportAttr("tabLayoutIndicator", new TabLayoutIndicatorAttr());</code>

  • 最后我們就可以正常使用了别渔,<code>dynamicAddSkinEnableView(tablayout, "tabLayoutIndicator", R.color.colorPrimaryDark);</code>

3. 關(guān)于字體切換

還是遵守本項(xiàng)目的約定大于配置的原則,所有的字體都放到 assets/fonts 文件夾下

如何切換字體:
<code> SkinManager.getInstance().loadFont("xx.ttf")</code>

關(guān)于切換字體需要配置的東西:
如果只是單純的想要字體切換這個(gè)功能惧互。只需<code>集成步驟</code>中的前三步就行了哎媚。

注:字體切換功能默認(rèn)不開啟,需要字體切換功能請(qǐng)?jiān)谀愕腁pplication中加入<code>SkinConfig.setCanChangeFont(true);</code>

4. 其他一些重要的api

  1. SkinConfig.isDefaultSkin(context):判斷當(dāng)前皮膚是否是默認(rèn)皮膚

  2. SkinManager.getInstance().restoreDefaultTheme(): 重置默認(rèn)皮膚

  3. dynamicAddView:當(dāng)動(dòng)態(tài)創(chuàng)建的View也需要換膚的時(shí)候,就可以調(diào)用 dynamicAddView


5. 使用注意事項(xiàng):

  1. 換膚默認(rèn)只支持 android 的常用控件壹哺,對(duì)于支持庫(kù)的控件和自定義控件的換膚需要?jiǎng)討B(tài)添加(例如: <code>dynamicAddSkinEnableView(toolbar, "background", R.color.colorPrimaryDark);</code>)抄伍,在布局文件中使用<code>skin:enable="true"</code>是無(wú)效的。

  2. 默認(rèn)不支持狀態(tài)欄顏色的更改管宵,如果需要換膚的同時(shí)也要更改狀態(tài)欄顏色截珍,請(qǐng)到您的Application文件中加入<code>SkinConfig.setCanChangeStatusColor(true);</code>,狀態(tài)欄的顏色值來(lái)源于<code>colorPrimaryDark</code>

  3. 本開源庫(kù)使用的 Activity 是 AppCompatActivity箩朴,使用的 Fragment 是 android.support.v4.app.Fragment

  4. 有換膚需求 View 所使用的資源一定要是引用值岗喉,例如:@color/red,而不是 #ff0000

補(bǔ)充:支持庫(kù)控件的皮膚修改

1.FloatingActionButton修改backgroundTint

需要自定義:

public class FabButtonAttr extends SkinAttr {
    @Override
    public void apply(View view) {
        if (view instanceof FloatingActionButton) {
            FloatingActionButton fb = (FloatingActionButton) view;
            if (RES_TYPE_NAME_COLOR.equals(attrValueTypeName)) {
                int color = SkinManager.getInstance().getColor(attrValueRefId);
                fb.setBackgroundTintList(ColorStateList.valueOf(color));
            } else if (RES_TYPE_NAME_DRAWABLE.equals(attrValueTypeName)) {
                //  tv.setDivider(SkinManager.getInstance().getDrawable(attrValueRefId));
            }
        }
    }
}

Application中添加:

  SkinConfig.addSupportAttr("backgroundTint",new FabButtonAttr());

使用:

   //添加改變的組件
        dynamicAddView(fab, "backgroundTint", R.color.colorPrimary);

2.NavigationView 修改點(diǎn)擊時(shí)的item顏色

需要自定義:

public class NavigationViewAttr extends SkinAttr {
    @Override
    public void apply(View view) {
        if (view instanceof NavigationView) {
            Log.i("TabLayoutAttr", "apply");
            NavigationView nv = (NavigationView) view;
            if (RES_TYPE_NAME_COLOR.equals(attrValueTypeName)) {
                Log.i("TabLayoutAttr", "apply color");
                int color = SkinManager.getInstance().getColor(attrValueRefId);
                nv.setItemTextColor(createSelector(color));
                nv.setItemIconTintList(createSelector(color));
            } else if (RES_TYPE_NAME_DRAWABLE.equals(attrValueTypeName)) {
                Log.i("TabLayoutAttr", "apply drawable");
                //  tv.setDivider(SkinManager.getInstance().getDrawable(attrValueRefId));
            }
        }
    }

    private ColorStateList createSelector(int color) {
        int statePressed = android.R.attr.state_checked;
        int stateChecked = android.R.attr.state_checked;
        int[][] state = {{statePressed}, {-statePressed}, {stateChecked}, {-stateChecked}};
        int color1 = color;
        int color2 = Color.parseColor("#6E6E6E");
        int color3 = color;
        int color4 = Color.parseColor("#6E6E6E");
        int[] colors = {color1, color2, color3, color4};
        ColorStateList colorStateList = new ColorStateList(state, colors);
        return colorStateList;
    }
}

Application中添加:

   SkinConfig.addSupportAttr("navigationViewMenu",new NavigationViewAttr());

使用:

   //添加改變的組件
    dynamicAddView(navigationView.getHeaderView(0), "background", R.color.colorPrimary);
        dynamicAddView(navigationView, "navigationViewMenu", R.color.colorPrimary);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末炸庞,一起剝皮案震驚了整個(gè)濱河市钱床,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌埠居,老刑警劉巖查牌,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件事期,死亡現(xiàn)場(chǎng)離奇詭異纸颜,居然都是意外死亡兽泣,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門胁孙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)唠倦,“玉大人,你說(shuō)我怎么就攤上這事涮较〕肀牵” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵狂票,是天一觀的道長(zhǎng)候齿。 經(jīng)常有香客問我,道長(zhǎng)苫亦,這世上最難降的妖魔是什么毛肋? 我笑而不...
    開封第一講書人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮屋剑,結(jié)果婚禮上润匙,老公的妹妹穿的比我還像新娘。我一直安慰自己唉匾,他們只是感情好孕讳,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著巍膘,像睡著了一般厂财。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上峡懈,一...
    開封第一講書人閱讀 51,598評(píng)論 1 305
  • 那天璃饱,我揣著相機(jī)與錄音,去河邊找鬼肪康。 笑死荚恶,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的磷支。 我是一名探鬼主播谒撼,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼雾狈!你這毒婦竟也來(lái)了廓潜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辩蛋,沒想到半個(gè)月后呻畸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡堪澎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年擂错,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片樱蛤。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖剑鞍,靈堂內(nèi)的尸體忽然破棺而出昨凡,到底是詐尸還是另有隱情,我是刑警寧澤蚁署,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布便脊,位于F島的核電站,受9級(jí)特大地震影響光戈,放射性物質(zhì)發(fā)生泄漏哪痰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一久妆、第九天 我趴在偏房一處隱蔽的房頂上張望晌杰。 院中可真熱鬧,春花似錦筷弦、人聲如沸肋演。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)爹殊。三九已至,卻和暖如春奸绷,著一層夾襖步出監(jiān)牢的瞬間梗夸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工号醉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留反症,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓扣癣,卻偏偏與公主長(zhǎng)得像惰帽,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子父虑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,152評(píng)論 25 707
  • afinalAfinal是一個(gè)android的ioc该酗,orm框架 https://github.com/yangf...
    passiontim閱讀 15,434評(píng)論 2 45
  • 1: 獲取控件寬高 控件View有g(shù)etHeight()和getwidth()方法可以獲取寬高,但是如果直接在on...
    自由人是工程師閱讀 1,780評(píng)論 0 0
  • 前情回顧:渣男日記(八) 愛情和謀殺一樣,即使閉口不說(shuō)呜魄,也會(huì)隨著時(shí)間慢慢暴露無(wú)遺悔叽。喜歡上一個(gè)人時(shí),你的心思就全不在...
    聽任蔓草湮路閱讀 934評(píng)論 0 1
  • 初中最后一個(gè)暑假的時(shí)候,我變成了插班生睹晒。原因是我的學(xué)習(xí)成績(jī)太差趟庄,特別是英語(yǔ),簡(jiǎn)直讓老師懷疑人生伪很,他勤勤懇懇戚啥、連罵帶...
    半掩窗閱讀 808評(píng)論 0 0