如何自定義FragmentTabHost中某一個(gè)Tab的點(diǎn)擊效果

問題

iOS上的Tab Bar相信大家都很熟悉了,就是界面底部幾個(gè)按鈕禀忆,點(diǎn)擊可以切換子頁面士葫。
而在Android上,可以用support v4中的FragmentTabHost來實(shí)現(xiàn)類似效果拱镐,它繼承自TabHost,每個(gè)子頁面都是一個(gè)Fragment持际。
今天遇到一個(gè)需求沃琅,需要在點(diǎn)擊Tab按鈕后,不切換子頁面蜘欲,而是跳轉(zhuǎn)到一個(gè)新的頁面益眉。通過查閱文檔,FragmentTabHost與其父類TabHost似乎都沒有提供相關(guān)函數(shù)可以自定義Tab的點(diǎn)擊事件姥份。只有一個(gè)當(dāng)Tab切換完成后的回調(diào)監(jiān)聽OnTabChangeListener郭脂,但是切換已經(jīng)完成為時(shí)已晚啊。
在查閱文檔無果后殿衰,我祭出了Google朱庆,但是卻苦于不知道該如何組織關(guān)鍵詞(英文不會,中文離譜)闷祥,試了幾個(gè)關(guān)鍵詞依然無果娱颊。既然如此,就嘗試看下源碼吧凯砍,沒想到最終還是非常簡單就可以解決問題箱硕,遂記錄一下。

首先我們來看一下FragmentTabHost的基本使用悟衩,來自官方文檔

mTabHost = new FragmentTabHost(getActivity());
mTabHost.setup(getActivity(), getChildFragmentManager(), R.id.fragment1);
mTabHost.addTab(mTabHost.newTabSpec("simple").setIndicator("Simple"), FragmentStackSupport.CountingFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec("contacts").setIndicator("Contacts"), LoaderCursorSupport.CursorLoaderListFragment.class, null);

第二行通過setup進(jìn)行初始化剧罩,三四行通過addTab方法添加了兩個(gè)Tab,我們就從Tab的添加入手座泳,開始追蹤源碼惠昔,看看它都做了什么,是如何設(shè)置每個(gè)Tab的點(diǎn)擊事件的挑势。以下的源碼經(jīng)過了簡化镇防,只保留部分關(guān)鍵信息。

源碼追蹤

首先是FragmentTabHost潮饱,它繼承自TabHost来氧,增加了一個(gè)addTab的重載方法,第二個(gè)參數(shù)接收Fragment的class,用于Fragment相關(guān)邏輯啦扬。在完成對Fragment的處理后中狂,繼續(xù)調(diào)用父類TabHostaddTab方法。

public class FragmentTabHost extends TabHost {

    public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
        ...    
        addTab(tabSpec);
    }

}

然后來到TabHost扑毡,其中成員變量mTabWidget是Tab的容器胃榕。在addTab方法中,先取出了Tab的View僚楞,然后執(zhí)行mTabWidget的addView勤晚,將Tab添加到容器中。

public class TabHost extends FrameLayout {
    private TabWidget mTabWidget;

    public void addTab(TabSpec tabSpec) {
        ...
        View tabIndicator = tabSpec.mIndicatorStrategy.createIndicatorView();
        ...
        mTabWidget.addView(tabIndicator);
        ...
    }

}

最后來到TabWidget泉褐,可以看到它繼承自我們的老朋友LinearLayout,這為Tab View提供了線性排布鸟蜡。在addView方法的最后膜赃,我們找到了為每個(gè)Tab設(shè)置點(diǎn)擊監(jiān)聽的地方。

public class TabWidget extends LinearLayout {

    @Override
    public void addView(View child) {
        ...
        super.addView(child);

        // TODO: detect this via geometry with a tabwidget listener rather
        // than potentially interfere with the view's listener
        child.setOnClickListener(new TabClickListener(getTabCount() - 1));
        child.setOnFocusChangeListener(this);
    }

}

解決問題

通過一路追蹤源碼揉忘,現(xiàn)在我們已經(jīng)知道了FragmentTabHost是如何設(shè)定每個(gè)Tab的點(diǎn)擊事件的跳座。最后設(shè)置監(jiān)聽器的地方給了我啟發(fā),假如能夠獲取到Tab View泣矛,就可以設(shè)置自己的點(diǎn)擊監(jiān)聽疲眷,同時(shí)覆蓋掉了系統(tǒng)的監(jiān)聽器,從而完成自定義點(diǎn)擊效果的任務(wù)您朽。
于是從TabWidget反過來查找獲取Tab View的方法狂丝。首先TabWidget提供了getChildTabViewAt(int index)方法,可以根據(jù)Tab的索引獲取到Tab View哗总。然后通過TabHostgetTabWidget可以獲取到TabWidget 几颜。得到目標(biāo)Tab View后,設(shè)定自己的OnClickListener讯屈,搞定任務(wù)蛋哭。
下面代碼演示了設(shè)置第一個(gè)Tab點(diǎn)擊事件的方法。

mTabHost.getTabWidget().getChildTabViewAt(0).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        
    }
});

總結(jié)

系統(tǒng)的源碼真的寫的非常清楚涮母,只要肯耐心看谆趾,很多問題都可以迎刃而解。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末叛本,一起剝皮案震驚了整個(gè)濱河市沪蓬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌炮赦,老刑警劉巖怜跑,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡性芬,警方通過查閱死者的電腦和手機(jī)峡眶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來植锉,“玉大人辫樱,你說我怎么就攤上這事】”樱” “怎么了狮暑?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長辉饱。 經(jīng)常有香客問我搬男,道長,這世上最難降的妖魔是什么彭沼? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任缔逛,我火速辦了婚禮,結(jié)果婚禮上姓惑,老公的妹妹穿的比我還像新娘褐奴。我一直安慰自己,他們只是感情好于毙,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布敦冬。 她就那樣靜靜地躺著,像睡著了一般唯沮。 火紅的嫁衣襯著肌膚如雪脖旱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天烂翰,我揣著相機(jī)與錄音夯缺,去河邊找鬼。 笑死甘耿,一個(gè)胖子當(dāng)著我的面吹牛踊兜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播佳恬,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼捏境,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了毁葱?” 一聲冷哼從身側(cè)響起垫言,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎倾剿,沒想到半個(gè)月后筷频,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚌成,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年凛捏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了担忧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,567評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡坯癣,死狀恐怖瓶盛,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情示罗,我是刑警寧澤惩猫,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站蚜点,受9級特大地震影響轧房,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜绍绘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一锯厢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧脯倒,春花似錦、人聲如沸捺氢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽摄乒。三九已至悠反,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間馍佑,已是汗流浹背斋否。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拭荤,地道東北人茵臭。 一個(gè)月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像舅世,于是被迫代替她去往敵國和親旦委。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評論 2 359

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