動(dòng)態(tài)換膚四(其他控件換膚)

前言

??上一篇文章中枉阵,將一些系統(tǒng)的 View 已經(jīng)完成換膚了译红。這篇文章我們會完成 Fragment、狀態(tài)欄兴溜、底部虛擬按鍵的換膚侦厚。

上一篇文章地址:http://www.reibang.com/p/1139df041cb6

Fragment 換膚

??我們需要使用到 TableLayout,所以添加一個(gè)依賴
compile 'com.android.support:design:26.+'拙徽,然后修改 MainActivity 的布局文件刨沦,并修改 MainActivity 給其添加幾個(gè) Fragment

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    android:background="?attr/colorAccent">

    <TextView
        android:id="@+id/tv_click"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="換膚"
        android:padding="10dp"
        android:background="#ffffff"
        android:layout_marginBottom="30dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv_other"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:textColor="@color/black"
        android:text="還原"
        android:background="@color/black"/>

    <TableLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize">

    </TableLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //...

        TabLayout tabLayout = (TabLayout) findViewById(R.id.tabLayout);
        ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);

        List<Fragment> list = new ArrayList<>();
        list.add(new MusicFragment());
        list.add(new VideoFragment());
        list.add(new RadioFragment());
        List<String> listTitle = new ArrayList<>();
        listTitle.add("音樂");
        listTitle.add("視頻");
        listTitle.add("電臺");
        MyFragmentPagerAdapter myFragmentPagerAdapter = new MyFragmentPagerAdapter
                (getSupportFragmentManager(), list, listTitle);
        viewPager.setAdapter(myFragmentPagerAdapter);
        tabLayout.setupWithViewPager(viewPager);
    }
}

??這里新建了幾個(gè) Fragment 并且顯示在 Activity 中,我們測試一下前面寫的系統(tǒng)的 View 換膚能否在 Fragment 里面進(jìn)行換膚


Fragment 換膚前

??點(diǎn)擊換膚按鈕


Fragment 換膚后

??我們發(fā)現(xiàn)膘怕,F(xiàn)ragment 里面也可以進(jìn)行換膚想诅,為什么呢?
??一個(gè) Fargment 里面岛心,我們重寫它的 onCreateView 方法后来破,onCreateView 方法里面的 LayoutInflater 會通過參數(shù)傳遞過來,我們通過查看 Fragment 的源碼會發(fā)現(xiàn)忘古,這個(gè) LayoutInfalter 是通過 mHost.onGetLayoutInflater(); 獲取的
image.png

image.png

??而我們的 Activity 繼承自


image.png

image.png

??在這個(gè) FragmentActivity 里面
image.png

??所以我們調(diào)用的是這個(gè) HostCallbacks 的 onGetLayoutInflater 方法
image.png

??通過一個(gè) cloneInContext 方法獲取的一個(gè) Activity讳癌,所以說跟 Activity 的 LayoutInflater 不是同一個(gè) LayoutInflater,而其實(shí)我們拿到的是 LayoutInflater 的子類:PhoneLayoutInflater
image.png

??這是 new 出來的存皂,所以跟 Activity 的 Inflater 不是同一個(gè)晌坤,我們繼續(xù)看 PhoneLayoutInflater 的構(gòu)造函數(shù)
image.png

??他會調(diào)用父類的構(gòu)造函數(shù)


image.png

??原來是這樣,里面的 mFactory 旦袋、mFactory2 是同一個(gè)骤菠。也就是說,雖然 Fragment 的 LayoutInflater 跟我們的 Activity 的 LayoutInflater 不是同一個(gè)疤孕,但是他們里面的 Factory 是同一個(gè)商乎。
??也許細(xì)心的同學(xué),會看見這一行代碼
image.png

??這一行代碼就設(shè)置 Factory2祭阀,那我們設(shè)置了 Factory2 他也設(shè)置了 Factory2 為什么會用到我們的鹉戚?原因是這里面他使用了工廠合并鲜戒,我們看下面的源碼
image.png

image.png

??所以說,最終還是會回調(diào)到我們自定義的 Factory2 里面抹凳,那這也就解釋了為什么我們沒有給 Fragment 做任何操作遏餐,F(xiàn)ragment 就能換膚的原因。

狀態(tài)欄和底部虛擬按鍵換膚

??我們先看一張圖


image.png

??很多人都見過這張圖赢底,狀態(tài)欄是由 statusBarColor 和 colorPrimaryDark 來控制失都,底部虛擬按鍵是由 navigationBarColor 來控制的。

注意:其中 colorPrimaryDark 的全路徑是:android.support.v7.appcompat.R.attr.colorPrimaryDark
statusBarColor 的全路徑是:android.R.attr.statusBarColor
navigationBarColor 的全路徑是:android.R.attr.navigationBarColor

??狀態(tài)欄換膚和底部虛擬按鍵換膚有對應(yīng)的 api 可以調(diào)用幸冻,但是需要在 Android 5.0 版本以上才可以粹庞。注意狀態(tài)欄的配置有兩個(gè),我們優(yōu)先從 statusBarColor 里面去找洽损,如果沒找到就去 colorPrimaryDark 中找庞溜。
??在 SkinThemeUtils 增加如下方法

    /**
     * 狀態(tài)欄、底部虛擬按鈕換膚
     */
    public static void updateStatusBar(Activity activity) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            return ;
        }
        int[] resId = getResId(activity, STATUSBAR_COLOR_ATTRS);
        if(resId[0] == 0){
            resId[0] = getResId(activity,APPCOMPAT_COLOR_PRIMARY_DARK_ATTR)[0];
        }
        //更換狀態(tài)欄
        if(resId[0] != 0){
            activity.getWindow().setStatusBarColor(SkinResources.getInstance().getColor(resId[0]));
        }
        //更換底部虛擬按鍵
        if(resId[1] != 0){
            activity.getWindow().setNavigationBarColor(SkinResources.getInstance().getColor(resId[1]));
        }
    }

??然后我們在我們的主包下面添加如下代碼


image.png

image.png

??這樣我們確保就能在 Android 5.0 系統(tǒng)以上的手機(jī)可以使用使用 navigationBarColor 這個(gè)屬性并且可以進(jìn)行換膚碑定。然后我們把皮膚包中的 colorPrimaryDark 設(shè)置成白色流码,也就是最終換膚后系統(tǒng)狀態(tài)欄和底部虛擬按鍵的背景色都換成了白色。
??最后不傅,就是要調(diào)用狀態(tài)欄換膚的功能了旅掂。分別在 Activity 創(chuàng)建的時(shí)候以及我們點(diǎn)擊換膚按鈕的時(shí)候調(diào)用一次即可。


換膚前

換膚后

還原
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末访娶,一起剝皮案震驚了整個(gè)濱河市商虐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌崖疤,老刑警劉巖秘车,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異劫哼,居然都是意外死亡叮趴,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門权烧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來眯亦,“玉大人,你說我怎么就攤上這事般码∑蘼剩” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵板祝,是天一觀的道長宫静。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么孤里? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任伏伯,我火速辦了婚禮,結(jié)果婚禮上捌袜,老公的妹妹穿的比我還像新娘说搅。我一直安慰自己,他們只是感情好琢蛤,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布蜓堕。 她就那樣靜靜地躺著抛虏,像睡著了一般博其。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上迂猴,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天慕淡,我揣著相機(jī)與錄音,去河邊找鬼沸毁。 笑死峰髓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的息尺。 我是一名探鬼主播携兵,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼搂誉!你這毒婦竟也來了徐紧?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤炭懊,失蹤者是張志新(化名)和其女友劉穎并级,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體侮腹,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嘲碧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了父阻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片愈涩。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖加矛,靈堂內(nèi)的尸體忽然破棺而出履婉,到底是詐尸還是另有隱情,我是刑警寧澤荒椭,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布谐鼎,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏狸棍。R本人自食惡果不足惜身害,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望草戈。 院中可真熱鬧塌鸯,春花似錦、人聲如沸唐片。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽费韭。三九已至茧球,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間星持,已是汗流浹背抢埋。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留督暂,地道東北人揪垄。 一個(gè)月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像逻翁,于是被迫代替她去往敵國和親饥努。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,498評論 25 707
  • 內(nèi)容抽屜菜單ListViewWebViewSwitchButton按鈕點(diǎn)贊按鈕進(jìn)度條TabLayout圖標(biāo)下拉刷新...
    皇小弟閱讀 46,708評論 22 664
  • Android UI相關(guān)開源項(xiàng)目庫匯總OpenDigg 抽屜菜單MaterialDrawer ★7337 - 安卓...
    黃海佳閱讀 8,690評論 3 77
  • 三八理論: 就是上帝給了每個(gè)人公平的三個(gè)8小時(shí)八回,第一個(gè)8小時(shí)大家都在工作第二個(gè)8小時(shí)大家都在睡覺酷愧,人與人的區(qū)別...
    小芭蕾_7ed2閱讀 364評論 0 0
  • 有很多話想跟你說 總結(jié)如下 q“我很想你”
    faim閱讀 294評論 0 0