Material Design 控件知識(shí)梳理(8) - TabLayout

Material Design 控件知識(shí)梳理(1) - Android Design Support Library 是什么
Material Design 控件知識(shí)梳理(2) - AppBarLayout & CollapsingToolbarLayout
Material Design 控件知識(shí)梳理(3) - BottomSheet && BottomSheetDialog && BottomSheetDialogFragment
Material Design 控件知識(shí)梳理(4) - FloatingActionButton
Material Design 控件知識(shí)梳理(5) - DrawerLayout && NavigationView
Material Design 控件知識(shí)梳理(6) - Snackbar
Material Design 控件知識(shí)梳理(7) - BottomNavigationBar
Material Design 控件知識(shí)梳理(8) - TabLayout
Material Design 控件知識(shí)梳理(9) - TextInputLayout

一、概述

前面我們介紹了BottomNavigationBarTabLayout和它的作用類(lèi)似谋减,都是方便用戶(hù)進(jìn)行頁(yè)面之間的切換坚嗜。

二坏为、TabLayout的基本用法

下面陨囊,我們先演示一遍TabLayout的基本用法
第一步:引入依賴(lài):

compile 'com.android.support:design:25.3.1'

第二步:定義布局,這里使用了最常用的TabLayout+ViewPager的結(jié)構(gòu):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.demo.lizejun.repotransition.TabLayoutActivity">
    <android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabMode="scrollable"
        app:tabGravity="center"/>
    <android.support.v4.view.ViewPager
        android:id="@+id/vp_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

第三步:定義ViewPagerAdapter剧辐,這里需要重寫(xiě)getPageTitle方法寒亥,它就對(duì)應(yīng)的是TabLayout當(dāng)中的文案:

public class ViewPagerAdapter extends PagerAdapter {

    private List<String> mTitles;

    public ViewPagerAdapter(List<String> title) {
        mTitles = title;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        ViewGroup itemView = (ViewGroup) LayoutInflater.from(container.getContext()).inflate(R.layout.item_view_pager, container, false);
        container.addView(itemView);
        TextView tv = (TextView) itemView.findViewById(R.id.tv_title);
        tv.setText(mTitles.get(position));
        return itemView;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View) object);
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public int getCount() {
        return mTitles.size();
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return mTitles.get(position);
    }
}

第四步:給ViewPager設(shè)置數(shù)據(jù),并把ViewPagerTabLayout關(guān)聯(lián)起來(lái):

public class TabLayoutActivity extends AppCompatActivity {

    private static final String[] TITLE_SHORT = new String[] {
            "深圳","南京","內(nèi)蒙古"
    };

    private static final String[] TITLE_LONG = new String[] {
            "深圳","南京","內(nèi)蒙古呼和浩特","廣西壯族自治區(qū)","上海","北京","天津"
    };

    private ViewPager mViewPager;
    private TabLayout mTabLayout;
    private ViewPagerAdapter mViewPagerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tab_layout);
        initViewPager();
        initTabLayout();
    }

    private void initViewPager() {
        mViewPager = (ViewPager) findViewById(R.id.vp_content);
        List<String> titles = new ArrayList<>();
        Collections.addAll(titles, TITLE_LONG);
        mViewPagerAdapter = new ViewPagerAdapter(titles);
        mViewPager.setAdapter(mViewPagerAdapter);
    }

    private void initTabLayout() {
        mTabLayout = (TabLayout) findViewById(R.id.tab_layout);
        mTabLayout.setupWithViewPager(mViewPager);
    }

}

最終的效果為:


三浙于、TabLayout相關(guān)設(shè)置

3.1 TabItem的外觀設(shè)置

對(duì)于每個(gè)TabItem的外觀护盈,TabLayout我們比較常用的屬性有:

  • 未選中TabItem的文本顏色:app:tabTextColor
  • 選中TabItem的文本顏色app:tabSelectedTextColor
  • 底部滑動(dòng)條的顏色:app:tabIndicatorColor
  • 底部滑動(dòng)條的高度:app:tabIndicatorHeight
  • TabItem的背景:app:tabBackground

我們?cè)诘诙?jié)的基礎(chǔ)上進(jìn)行修改:

<android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabMode="scrollable"
        app:tabGravity="center"
        app:tabTextColor="@android:color/darker_gray"
        app:tabSelectedTextColor="@android:color/holo_orange_dark"
        app:tabIndicatorColor="@android:color/holo_orange_dark"
        app:tabIndicatorHeight="2dp"
        app:tabBackground="@android:color/transparent" />

最終展現(xiàn)的效果為:


3.2 TabItem的寬高相關(guān)設(shè)置

有兩個(gè)關(guān)于寬度的屬性比較重要:tabMinWidthtabMaxWidth,它允許我們這是每個(gè)TabItem的最小和最大寬度羞酗。
此外腐宋,我們還可以設(shè)置TabItem四個(gè)維度的Padding

3.3 tabModetabGravity

上面只是決定了單個(gè)TabItem的外觀檀轨,而TabItemTabLayout當(dāng)中的擺放規(guī)則需要由這兩個(gè)屬性來(lái)決定胸竞,它們可選的值分別為:

  • tabModefixed或者scrollable
  • tabGravityfill或者center

這兩個(gè)屬性分別通過(guò):app:tabModeapp:tabGravity來(lái)設(shè)置,下面参萄,我們就來(lái)解釋這幾個(gè)值的含義卫枝。

3.3.1 tabMode=fixed

在這種模式下,每個(gè)TabItem的寬度都是相等的讹挎,并且所有的TabItem加起來(lái)的寬度不會(huì)大于TabLayout的寬度校赤,最終展現(xiàn)的結(jié)果還需要依賴(lài)于tabGravity屬性:

  • tabGravity=fill
    要求所有TabItem加起來(lái)的寬度等于TabLayout的寬度吆玖,也就是下面的效果
  • tabGravity=center
    不要求TabItem加起來(lái)的寬度等于TabLayout的寬度,會(huì)根據(jù)每個(gè)TabItem的屬性马篮,計(jì)算出TabItem的寬度沾乘,然后取它們中的最大值乘上TabItem的個(gè)數(shù),當(dāng)這一數(shù)值小于TabLayout的寬度時(shí)浑测,會(huì)將每個(gè)TabItem的寬度設(shè)置為這個(gè)最大值翅阵,并將它們放置在整個(gè)TabLayout的中間,而如果這一數(shù)值大于TabLayout的寬度迁央,那么會(huì)將它們?cè)?code>TabLayout中均勻排列掷匠。

3.3.2 tabMode=scrollable

tabMode=fixed模式下,TabItem的位置是固定的岖圈,并且它們加起來(lái)的寬度不會(huì)大于TabLayout的寬度讹语,而在scrollable模式下則沒(méi)有這一限制,只需要計(jì)算好每個(gè)TabItem的寬度蜂科,然后把它們排列在TabLayout中就好了募强,可以通過(guò)拖動(dòng)的方式查看更多的TabItem,并且當(dāng)tabMode=scrollable時(shí)崇摄,tabGravity其實(shí)并沒(méi)有作用,下面是tabMode=scrollable的事例:


在這種模式下慌烧,每個(gè)TabItem的寬度默認(rèn)情況下是根據(jù)文字的寬度計(jì)算出來(lái)的逐抑,如果我們希望進(jìn)行相應(yīng)的限制,那么可以修改tabMinWidth或者tabMaxWidth屬性屹蚊。

3.4 設(shè)置監(jiān)聽(tīng)

mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {

            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                Log.d("onTabSelected", "position=" + tab.getPosition());
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
                Log.d("onTabUnselected", "position=" + tab.getPosition());

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {
                Log.d("onTabReselected", "position=" + tab.getPosition());

            }
});
  • onTabSelected厕氨,某個(gè)TabItem從未選中狀態(tài)變?yōu)檫x中狀態(tài)時(shí)回調(diào)
  • onTabUnselected,某個(gè)TabItem從選中變?yōu)槲催x中時(shí)回調(diào)
  • onTabReselected汹粤,某個(gè)TabItem已經(jīng)處于選中狀態(tài)命斧,但是它又被再次點(diǎn)擊了,那么回調(diào)這個(gè)函數(shù)嘱兼。

四国葬、TabLayout + ViewPager

使用TabLayout時(shí),一般都是采用ViewPager來(lái)管理多個(gè)子界面芹壕,而TabLayout也十分貼心地提供了方法讓它和ViewPager的滾動(dòng)關(guān)聯(lián)起來(lái)汇四,當(dāng)點(diǎn)擊TabLayout中的Item時(shí),會(huì)切換到ViewPager對(duì)應(yīng)的界面踢涌,而如果滑動(dòng)了ViewPager通孽,那么TabLayout也會(huì)切換到對(duì)應(yīng)的TabItem
我們所需要的只是下面這句設(shè)置:

mTabLayout.setupWithViewPager(mViewPager);

為了能讓TabLayout知道TabItem的標(biāo)題睁壁,需要重寫(xiě)ViewPager所對(duì)應(yīng)的PagerAdaptergetPageTitle的方法:

@Override
public CharSequence getPageTitle(int position) {
    return mTitles.get(position);
}

雖然TabLayout并沒(méi)有提供切換到某個(gè)具體位置TabItem的方法背苦,但是其實(shí)這一過(guò)程這完全可以通過(guò)mViewPager.setCurrentItem(int item)來(lái)實(shí)現(xiàn)互捌。


更多文章,歡迎訪問(wèn)我的 Android 知識(shí)梳理系列:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末行剂,一起剝皮案震驚了整個(gè)濱河市秕噪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌硼讽,老刑警劉巖巢价,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異固阁,居然都是意外死亡壤躲,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)备燃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)碉克,“玉大人,你說(shuō)我怎么就攤上這事并齐÷┞螅” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵况褪,是天一觀的道長(zhǎng)撕贞。 經(jīng)常有香客問(wèn)我,道長(zhǎng)测垛,這世上最難降的妖魔是什么捏膨? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮食侮,結(jié)果婚禮上号涯,老公的妹妹穿的比我還像新娘。我一直安慰自己锯七,他們只是感情好链快,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著眉尸,像睡著了一般域蜗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上效五,一...
    開(kāi)封第一講書(shū)人閱讀 49,749評(píng)論 1 289
  • 那天地消,我揣著相機(jī)與錄音,去河邊找鬼畏妖。 笑死脉执,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的戒劫。 我是一名探鬼主播半夷,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼婆廊,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了巫橄?” 一聲冷哼從身側(cè)響起淘邻,我...
    開(kāi)封第一講書(shū)人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎湘换,沒(méi)想到半個(gè)月后宾舅,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡彩倚,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年筹我,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帆离。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蔬蕊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出哥谷,到底是詐尸還是另有隱情岸夯,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布们妥,位于F島的核電站猜扮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏监婶。R本人自食惡果不足惜破镰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望压储。 院中可真熱鬧,春花似錦源譬、人聲如沸集惋。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)刮刑。三九已至,卻和暖如春养渴,著一層夾襖步出監(jiān)牢的瞬間雷绢,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工理卑, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留翘紊,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓藐唠,卻偏偏與公主長(zhǎng)得像帆疟,于是被迫代替她去往敵國(guó)和親鹉究。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

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