TabLayout基本属性全解

前言

之前讲过一篇TabLayout实现顶部导航的文章,这篇文章,来详细介绍下TabLayout的一些基本使用,让大家以后更加方便的使用。

这篇文章涉及的内容有:

  1. 控件库的导入
  2. TabLayout导航UI的快速实现
  3. TabLayout均分显示的问题
  4. 设置TabLayout选中和没选中时字体颜色
  5. 改变指示器下标的颜色
  6. 改变整个TabLayout的颜色
  7. 改变TabLayout内部字体大小
  8. 改变指示器下标的高度
  9. 添加图标
  10. 加入Padding
  11. Tab的宽度限制
  12. Tab的“Margin”
  13. 和ViewPager的联动
  14. 默认选中某项
  15. 监听事件
  16. TabLayout点击事件
一.控件库的导入

TabLayout属于android的Design库中的控件,所以需要在使用之前在项目的app对应的buildle.gradle中导入该库:

    //TabLayout
    implementation 'com.android.support:design:27.1.1'
    implementation 'com.android.support:support-v4:27.1.1'
二.TabLayout导航UI的快速实现

TabLayout导航ui的实现有两种方式,xml的实现和代码的实现。

1.1 xml实现TabLayout导航栏

直接在TabLayout内部加入TabItem即可,

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    tools:context="com.android.testdemo.main.MainActivity">

    <android.support.design.widget.TabLayout
        android:id="@+id/tablayout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">

        <android.support.design.widget.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Tab1"/>
        <android.support.design.widget.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Tab2"/>
        <android.support.design.widget.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Tab3"/>
        <android.support.design.widget.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Tab4"/>
    </android.support.design.widget.TabLayout>
</android.support.constraint.ConstraintLayout>
1.2 代码实现TabLayout导航栏

先声明一个导航 代码实现如下:

    @BindView(R.id.tablayout)
    TabLayout mTabLayout;

    private String mTitles[] = {
            "上海", "头条推荐", "生活", "娱乐八卦", "体育",
            "段子", "美食", "电影", "科技", "搞笑",
            "社会", "财经", "时尚", "汽车", "军事",
            "小说", "育儿", "职场", "萌宠", "游戏",
            "健康", "动漫", "互联网"};

        //TabLayout的基本使用
        for(int i=0;i<4;i++){
            TabLayout.Tab tab=mTabLayout.newTab();
            tab.setTag(i);
            tab.setText(mTitles[i]);
            mTabLayout.addTab(tab);
        }

这两种方法的区别是xml添加的只能是固定的几个item,若item的个数超过一屏宽度则不能使用这种方式布局,而代码布局则能实现item的个数超过一屏宽度的布局。
下面给出效果图:


xml实现TabLayout布局.gif
三.TabLayout均分显示的问题

当导航过多的时候,使用app:tabMode="scrollable"属性,能实现滑动均分,当导航不足一屏的时候,去掉app:tabMode="scrollable"才能实现均分展示.
xml中显示如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    tools:context="com.android.testdemo.main.MainActivity">

    <android.support.design.widget.TabLayout
        android:id="@+id/tablayout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">
    </android.support.design.widget.TabLayout>
</android.support.constraint.ConstraintLayout>

代码如下:

        for(int i=0;i<4;i++){
            TabLayout.Tab tab=mTabLayout.newTab();
            tab.setTag(i);
            tab.setText(mTitles[i]);
            mTabLayout.addTab(tab);
        }

效果图:


TabLayout均分1.gif

当item个数很多的时候,xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    tools:context="com.android.testdemo.main.MainActivity">

    <android.support.design.widget.TabLayout
        android:id="@+id/tablayout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:tabMode="scrollable"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">
    </android.support.design.widget.TabLayout>
</android.support.constraint.ConstraintLayout>

代码如下:

  //TabLayout的基本使用
        for(int i=0;i<mTitles.length;i++){
            TabLayout.Tab tab=mTabLayout.newTab();
            tab.setTag(i);
            tab.setText(mTitles[i]);
            mTabLayout.addTab(tab);
        }

效果图如下:


TabLayout均分2.gif
四.设置TabLayout选中和没选中时字体颜色

设置选中和没选中的颜色可以在xml中设置,也可以在代码中设置

4.1xml中设置
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    tools:context="com.android.testdemo.main.MainActivity">

    <!--app:tabSelectedTextColor="@color/red"//选中色-->
    <!--tabTextColor="@color/blue"//未选中色-->
    <android.support.design.widget.TabLayout
        android:id="@+id/tablayout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:tabSelectedTextColor="@color/red"
        app:tabTextColor="@color/blue"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">
    </android.support.design.widget.TabLayout>
</android.support.constraint.ConstraintLayout>
4.2代码中设置

代码中设置的时候,xml不需要做相关设置:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    tools:context="com.android.testdemo.main.MainActivity">

    <android.support.design.widget.TabLayout
        android:id="@+id/tablayout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">
    </android.support.design.widget.TabLayout>
</android.support.constraint.ConstraintLayout>

代码设置如下:

      //设置tab文本的没有选中(第一个参数)和选中(第二个参数)的颜色
      mTabLayout.setTabTextColors(Color.GREEN, Color.RED);

效果图如下:


设置TabLayout选中和没选中时字体颜色.gif
五. 改变指示器下标的颜色

直接在xml中设置:app:tabIndicatorColor="@color/green",xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    tools:context="com.android.testdemo.main.MainActivity">

    <android.support.design.widget.TabLayout
        android:id="@+id/tablayout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:tabIndicatorColor="@color/green"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">
    </android.support.design.widget.TabLayout>
</android.support.constraint.ConstraintLayout>

效果图如下:


改变指示器下标的颜色.gif
六. 改变整个TabLayout的颜色

直接在xml中设置:app:tabBackground="@color/blue",xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    tools:context="com.android.testdemo.main.MainActivity">

    <android.support.design.widget.TabLayout
        android:id="@+id/tablayout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:tabBackground="@color/blue"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">
    </android.support.design.widget.TabLayout>
</android.support.constraint.ConstraintLayout>

效果图:


改变整个TabLayout的颜色.png
七.改变TabLayout内部字体大小

直接在xml中设置:app:tabTextAppearance="@android:style/TextAppearance.Holo.Large",只有这一种设置方法,文字大小固定,比较不灵活,代码如下:

    <android.support.design.widget.TabLayout
        android:id="@+id/tablayout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
     app:tabTextAppearance="@android:style/TextAppearance.Holo.Large"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">
    </android.support.design.widget.TabLayout>

效果图如下:


改变TabLayout内部字体大小.png
八.改变指示器下标的高度

直接在xml中设置:app:tabIndicatorHeight="6dp",代码如下:

    <android.support.design.widget.TabLayout
        android:id="@+id/tablayout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:tabIndicatorHeight="6dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">
    </android.support.design.widget.TabLayout>

效果图如下:


设置指示器的高度为6dp.png

当设置指示器的高度为0dp,或者设置指示器颜色透明,即可实现没有下标指示器的效果,这里我设置的是高度为0dp:

    <android.support.design.widget.TabLayout
        android:id="@+id/tablayout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:tabIndicatorHeight="0dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">
    </android.support.design.widget.TabLayout>

效果图如下:


没有下标指示器的效果.png
九.添加图标

添加图标可以直接调用 TabLayout.Tab 的 setIcon() 方法,例如要新添加一个Tab1,并在Tab1上加一个 ic_launcher 图标,你可以像这样:

        //添加图标
        mTabLayout.addTab(mTabLayout.newTab().setText("Tab 1").setIcon(R.mipmap.ic_launcher));

效果图:


添加图标.png
十. 加入Padding

设置Tab内部的子控件的Padding:

app:tabPadding="xxdp"
app:tabPaddingTop="xxdp"
app:tabPaddingStart="xxdp"
app:tabPaddingEnd="xxdp"
app:tabPaddingBottom="xxdp"

设置整个TabLayout的Padding:

app:paddingEnd="xxdp"
app:paddingStart="xxdp"
十一.Tab的宽度限制

设置最大的tab宽度:

app:tabMaxWidth="xxdp"

设置最小的tab宽度:

app:tabMinWidth="xxdp"
十二.Tab的“Margin”

TabLayout开始位置的偏移量:

app:tabContentStart="50dp"
十三.和ViewPager的联动

之前已经讲过和ViewPager联动的一篇文章了,这里就不做详细讲解了。

十四.默认选中某项

如果你要设置默认选中第三项,你可以这样:

mTabLayout.getTabAt(2).select();
十五.监听事件

监听事件如下:

       //监听事件
        mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                //选中了tab的逻辑
                LogUtil.i("======我选中了===="+tab.getTag());
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
                //未选中tab的逻辑
                LogUtil.i("======我未被选中===="+tab.getTag());
            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {
               //再次选中tab的逻辑
                LogUtil.i("======我再次被选中===="+tab.getTag());
            }
        });

这里需要注意的是,初始化进入的时候,监听事件的三个方法都不会执行,假设此时你的item选中的是index=0,当你点击index=1的那项时,onTabUnselected(TabLayout.Tab tab)执行的是index=0的tab,onTabSelected(TabLayout.Tab tab)会执行index=1的Tab,此时onTabReselected(TabLayout.Tab tab)不会执行。当item已经选中的是index=1的时候,你再点击这个index=1的item的时候,onTabSelected(TabLayout.Tab tab)和onTabUnselected(TabLayout.Tab tab)不会执行,onTabReselected(TabLayout.Tab tab)会执行,tab为你当前点击的tab。

十六.TabLayout点击事件

只需调用以下方法:

    /**TabLayout点击事件**/
    private void tabItemClick(){
        //if(!mTabLayout.getTabAt(position).isSelected())是为了实现选中后再响应点击事件,
        //TabLayout和ViewPager联合使用的时候会用到
        for (int i = 0; i < mTabLayout.getTabCount(); i++){
            TabLayout.Tab tab = mTabLayout.getTabAt(i);
            if (tab == null) return;
            //这里使用到反射,拿到Tab对象后获取Class
            Class c = tab.getClass();
            try {
                //Filed “字段、属性”的意思,c.getDeclaredField 获取私有属性。
                //"mView"是Tab的私有属性名称(可查看TabLayout源码),类型是 TabView,TabLayout私有内部类。
                Field field = c.getDeclaredField("mView");
                //值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查。
                //如果不这样会报如下错误
                // java.lang.IllegalAccessException:
                //Class com.test.accessible.Main
                //can not access
                //a member of class com.test.accessible.AccessibleTest
                //with modifiers "private"
                field.setAccessible(true);
                final View view = (View) field.get(tab);
                if (view == null) return;
                view.setTag(i);
                view.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        int position = (int) view.getTag();
                        //这里就可以根据业务需求处理点击事件了。
                        if(!mTabLayout.getTabAt(position).isSelected()){
                            return;
                        }
                        switch (position) {
                            case 0:
                                showShort("我是0");
                                break;
                            case 1:
                                showShort("我是1");
                                break;
                            case 2:
                                showShort("我是2");
                                break;
                            case 3:
                                showShort("我是3");
                                break;
                            default:
                                break;
                        }
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

其中switch-case中即是你要处理的点击事件的逻辑,这里需要注意的是

 if(!mTabLayout.getTabAt(position).isSelected()){
                            return;
                        }

这段代码即表示只有当前item被选中的情况下,点击事件才生效。这个方法可以用来处理TabLayout和ViewPager联动的情况下,仍需要在item上添加处理事件的情况。
点击事件效果图如下:


TabLayout点击事件.gif

ok,今天关于TabLayout相关知识就讲到这里了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容