TabLayout 和 ViewPager 组合使用

这篇主要要介绍Tablayout使用,因为在实际开发中TabLayout和ViewPager一起使用,所以下面主要是对这二者的结合使用。

介绍路线

  1. TabLayout 的两种添加Tab 的方式
  2. TabLayout 的常用布局设置
  3. TabLayout 的常用API
  4. TabLayout 的时间监听
  5. TabLayout + ViewPager 的两种布局
  6. TabLayout + ViewPager 实现

TabLayout 的两种添加Tab 的方式

  1. 通过布局创建
<android.support.design.widget.TabLayout
    android:id="@+id/tab_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.design.widget.TabItem
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="首页"
        />

    <android.support.design.widget.TabItem
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="分类"
        />

    <android.support.design.widget.TabItem
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="设置"
        />

</android.support.design.widget.TabLayout>
  1. 通过代码创建
mTabLayout = (TabLayout) findViewById(R.id.tab_layout);
tab1 = mTabLayout.newTab();
tab1.setText("首页");

tab2 = mTabLayout.newTab();
tab2.setText("视频");

tab3 = mTabLayout.newTab();
tab3.setText("我的");

mTabLayout.addTab(tab1);
mTabLayout.addTab(tab2);
mTabLayout.addTab(tab3);

的常用布局设置

  1. 显示模式

    可滑动: app:tabMode="scrollable"
    固定: app:tabMode="fixed"

  2. 指示器选项

    指示器高度 :app:tabIndicatorHeight="10dp"
    指示器颜色 :app:tabIndicatorColor="@color/colorPrimary"

  3. 文字选项

    选择的Tab的文字颜色:app:tabSelectedTextColor="#ffffff"
    未选择的Tab文字颜色:app:tabTextColor="#000000"
    文字样式:app:tabTextAppearance="@style/Base.TextAppearance.AppCompat.Large"

  4. 背景设置(两者没什么区别)

    android:background="@color/colorAccent"
    app:tabBackground="@color/colorPrimary"

  5. 标签距离

    app:tabPaddingStart="10dp"
    app:tabPaddingBottom="10dp"
    app:tabPadding="10dp"
    app:tabPaddingEnd="10dp"
    app:tabPaddingTop="10dp"

  6. 对齐方式

    居中显示:app:tabGravity="center"
    填充:app:tabGravity="fill"
    偏移:app:tabContentStart="200dp"(从左边开始偏移距离, 必须是可滑动的模式 scrollable)

  7. 标签宽度限制

    最大宽度:app:tabMaxWidth="50dp"
    最小宽度:app:tabMinWidth="100dp"

TabLayout 的常用API

以下全部是基于TabLayout mTabLayout;

  1. 创建标签

    TabLayout.Tab tab = mTabLayout.newTab();

  2. 添加标签

    mTabLayout.addTab(tab1);

  3. 删除标签

    删除标签

    TabLayout.Tab tab = mTabLayout.newTab();   
    mTabLayout.removeTab(tab);
    

    通过索引删除标签

    TabLayout.Tab tab = mTabLayout.newTab();
    mTabLayout.removeTab(tab);
    mTabLayout.removeTabAt(tab.getPosition());
    

    删除所有标签

    mTabLayout.removeAllTabs();
    
  4. 得到标签

    TabLayout.Tab tab = mTabLayout.getTabAt(tabIndex)

  5. 得到标签总数

    int tabCount = mTabLayout.getTabCount();

  6. 指示器设置

    高度
    mTabLayout.setSelectedTabIndicatorHeight(20);

    颜色
    mTabLayout.setSelectedTabIndicatorColor(Color.RED);

  7. 文本

/**
 * 源码结构
 * public void setTabTextColors(int normalColor, int selectedColor)
 */
mTabLayout.setTabTextColors(normalColor,  // 正常颜色
                            selectedColor); // 选择状态颜色
                            
void setTabTextColors (ColorStateList textColor) // 状态颜色
  1. 显示模式

    mTabLayout.setTabMode(TabLayout.MODE_FIXED);
    固定: TabLayout.MODE_FIXED
    滚动:TabLayout.MODE_SCROLLABLE

  2. 对齐方式

    获取Tab 对齐方式
    int tabGravity = mTabLayout.getTabGravity();

    设置对齐方式
    mTabLayout.setTabGravity(TabLayout.GRAVITY_CENTER);
    居中:TabLayout.GRAVITY_CENTER
    填充:TabLayout.GRAVITY_FILL

  3. 直接添加View 为Tab
    我们直接看加View 为 Tab 的三个方法:

    void addView(View child)
    child : 要添加的View

    void addView (View child,int index)
    child : 要添加的View
    index : 位置索引

    void addView (View child,int index,ViewGroup.LayoutParams params)
    child : 要添加的View
    index : 位置索引
    params : 布局参数

  4. 得到当前选择的位置

    mTabLayout.getSelectedTabPosition();

Tab 常用API

以下全部是基于TabLayout mTabLayout;
以下全部基于 TabLayout.Tab mTab = mTabLayout.newTab();

  1. 判断是否被选择

    mTab.isSelected();

  2. 设置为被选择状态

    mTab.select();

  3. 描述内容(如果你没用设置描述内容, 默认的是标签的标题)
  • 设置描述内容
    下面介绍两种设置方式

    直接设置描述内容
    mTab.setContentDescription("text content");

    通过资源文件设置
    mTab.setContentDescription(R.string.app_name);
    看一下原码,在源码种可以看到,最终还设通过setContentDescription方法进行设置的。

    @NonNull
    public Tab setContentDescription(@StringRes int resId) {
        if (mParent == null) {
            throw new IllegalArgumentException("Tab not attached to a TabLayout");
        }
        return setContentDescription(mParent.getResources().getText(resId));
    }
    
  • 获取描述内容

    CharSequence content = mTab.getContentDescription();
    String strContent = content.toString();
    
  1. 自定义标签的内容
  • 直接设置View方式自定义标签内容

    View view = LayoutInflater.from(mContext).inflate(R.layout.view1,null);
    mTab.setCustomView(view);
    
  • 通过资源文件进行设置
    mTab.setCustomView(R.layout.view1);
    贴一下源码(不解释):

    @NonNull
    public Tab setCustomView(@LayoutRes int resId) {
        final LayoutInflater inflater = LayoutInflater.from(mView.getContext());
        return setCustomView(inflater.inflate(resId, mView, false));
    }
    
  1. 标签的标签
    给Tab设置tag, 然后就可以通过tag得到Tab
  • 设置tag (直接看源码)

    TabLayout.Tab tab = mTab.setTag("tag");

    @NonNull
    public Tab setTag(@Nullable Object tag) {
        mTag = tag;
        return this;
    }
    

    从上面源码中可以看到,设的tag类型是object ,返回的是Tab 本身。

  • 获取tag(直接看源码,不解释)
    Object obj = mTab.getTag();

    @Nullable
    public Object getTag() {
        return mTag;
    }
    
  1. 添加图标
TabLayout.Tab tab = mTab.setIcon(R.mipmap.ic_launcher);
TabLayout.Tab tab = mTab.setIcon(drawable);
  1. 标题的文字
TabLayout.Tab tab = mTab.setText(R.string.app_name);
TabLayout.Tab tab = mTab.setText("Tab Name");
  1. 当前标签位置
    int position = mTab.getPosition();

TabLayout 的时间监听

给TabLayout 添加监听事件时,要实现 OnTabSelectedListener 接口。多说啰嗦直接上代码:

mTabLayout.addOnTabSelectedListener(listener);

---------

private TabLayout.OnTabSelectedListener listener = new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            //选择的tab
            Log.e("TT","onTabSelected:" + tab.getText().toString());
        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {
            //离开的那个tab
            Log.e("TT","onTabUnselected" + tab.getText().toString());
        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {
            //再次选择tab
            Log.e("TT","onTabReselected" + tab.getText().toString());
        }
    };

TabLayout + ViewPager 的两种布局

  1. TabLayout 在ViewPager 布局
<android.support.v4.view.ViewPager
    android:id="@+id/vp_viewpager"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabMode="fixed"
        app:tabGravity="fill">
    </android.support.design.widget.TabLayout>
</android.support.v4.view.ViewPager>
  1. TabLayout 在ViewPager 布局
<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

    </android.support.v4.view.ViewPager>

    <android.support.design.widget.TabLayout
        android:layout_alignParentBottom="true"
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabMode="fixed"
        app:tabGravity="fill">
        
    </android.support.design.widget.TabLayout>
</RelativeLayout>

在上面两种布局中可以看到,在上面我把TabLayout放在了ViewPager外面的底部,如果我们把TabLayout 放到ViewPager外面,我们可以灵活的摆放TabLayout的位置,在实际开发中大多数都是放在上面的,所以如果是在上面,就放在里面还是外面都没有影响。

TabLayout + ViewPager 实现

  1. TAbLayout 在 ViewPager 布局内。
    先上代码,代码很简单,看一下代码,然后在根据代码中注意的地方特殊说明一下。
public class MainActivity extends AppCompatActivity {

    private TabLayout mTabLayout;
    private ViewPager mViewPager;
    private List<View> viewList = new ArrayList<>(3);
    private String[] strs = {"首页","视频","我的"};

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

        View view = null;
        view = getLayoutInflater().inflate(R.layout.view1,null);
        viewList.add(view);

        view = getLayoutInflater().inflate(R.layout.view2,null);
        viewList.add(view);

        view = getLayoutInflater().inflate(R.layout.view3,null);
        viewList.add(view);

        initView();
        initEvn();
    }

    private void initEvn() {
        mTabLayout.addOnTabSelectedListener(listener);
    }

    private void initView() {
        mTabLayout = (TabLayout) findViewById(R.id.tab_layout);
        mViewPager = (ViewPager) findViewById(R.id.vp_viewpager);
        mViewPager.setAdapter(new PagerAdapter() {
            @Override
            public int getCount() {
                return viewList.size();
            }

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

            @Override
            public Object instantiateItem(ViewGroup container, int position) {
                View view = viewList.get(position);
                container.addView(view);
                return view;
            }

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

            @Override
            public CharSequence getPageTitle(int position) {
                return strs[position];
            }
        });

    }

    private TabLayout.OnTabSelectedListener listener = new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            //选择的tab
            Log.e("TT","onTabSelected:" + tab.getText().toString());
        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {
            //离开的那个tab
            Log.e("TT","onTabUnselected" + tab.getText().toString());
        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {
            //再次选择tab
            Log.e("TT","onTabReselected" + tab.getText().toString());
        }
    };
}

上面代码中ViewPager的使用不用再说了,要说一下的是TabLayout如果不做其他操作是不需要添加获取的,也就是说不需要findViewById,ViewPager 会自动和TabLayout进行关联。

还需要注意的就是PagerAdapter中的下面这个方法:

private String[] strs = {"首页","视频","我的"};
---------------
@Override
public CharSequence getPageTitle(int position) {
    return strs[position];
}

getPageTitle 这个方法是设置TabLayout Tab 的文本标题的。

  1. TAbLayout 在 ViewPager 布局外。
    还是先上代码:
public class MainActivity extends AppCompatActivity {

    private TabLayout mTabLayout;
    private ViewPager mViewPager;
    private List<View> viewList = new ArrayList<>(3);
    private String[] strs = {"首页","视频","我的"};

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

        View view = null;
        view = getLayoutInflater().inflate(R.layout.view1,null);
        viewList.add(view);

        view = getLayoutInflater().inflate(R.layout.view2,null);
        viewList.add(view);

        view = getLayoutInflater().inflate(R.layout.view3,null);
        viewList.add(view);

        initView();
        initEvn();
    }

    private void initEvn() {
        mTabLayout.addOnTabSelectedListener(listener);
    }

    private void initView() {
        mTabLayout = (TabLayout) findViewById(R.id.tab_layout);
        mViewPager = (ViewPager) findViewById(R.id.vp_viewpager);
        mTabLayout.setupWithViewPager(mViewPager);
        mViewPager.setAdapter(new PagerAdapter() {
            @Override
            public int getCount() {
                return viewList.size();
            }

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

            @Override
            public Object instantiateItem(ViewGroup container, int position) {
                View view = viewList.get(position);
                container.addView(view);
                return view;
            }

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

            @Override
            public CharSequence getPageTitle(int position) {
                return strs[position];
            }
        });

    }

    private TabLayout.OnTabSelectedListener listener = new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            //选择的tab
            Log.e("TT","onTabSelected:" + tab.getText().toString());
        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {
            //离开的那个tab
            Log.e("TT","onTabUnselected" + tab.getText().toString());
        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {
            //再次选择tab
            Log.e("TT","onTabReselected" + tab.getText().toString());
        }
    };
}

看完这段代码,有人会认为这段代码和上面不是差不多嘛,对,我们就要注意一下不同的那一点。

不同的地方是,在这里我们要通过 findViewById 获取到TabLayout的setupWithViewPager(mViewPager)方法将ViewPager 对象设置到TabLayout 中和TabLayout进行关联。

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,565评论 25 707
  • TabLayout是属于容器控件, 提供水平显示Tab的效果. 常常和ViewPager配合使用. 我将全面地讲解...
    随心随性_0a25阅读 1,177评论 0 2
  • 内容抽屉菜单ListViewWebViewSwitchButton按钮点赞按钮进度条TabLayout图标下拉刷新...
    皇小弟阅读 46,406评论 22 663
  • 一、概述 它也是design中新出的一个控件,用来实现选项卡切换的效果,以前我们常用RadioGroup+Radi...
    Serenity那年阅读 2,318评论 0 9
  • 原文; 夫君子之行,静以修身,俭以养德。非淡泊无以明志,非宁静无以致远。夫学须静也,才须学也。非学无以广才,非志无...
    nr勿失勿忘阅读 848评论 0 1