一、概述

1.1 问题描述

TabLayout+ViewPager后,TabLayout的TabItem不显示的问题:

1.2 截图

二、结论

mTabs.setupWithViewPager(mViewPager); 语句的功能是:

  • 将 TabLayout、ViewPager 的监听事件同步
  • 对 TabLayout 的适配器进行重置
  • 对 TabLayout 的 TabItem 进行重置
  • 从 ViewPager 的 Adapter 中读取到每一页的标题,并为之创建 TabItem 添加到 TabLayout 中

解决方案是:

重写在 mViewPager 的 Adapter 中的如下方法,将每页的 Title 设置好:

	mViewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
} @Override
public int getCount() {
return mFragmentList.size();
} @Override
public CharSequence getPageTitle(int position) {
return mTitle[position];
}
});

三、问题探究

3.1 设置的代码

mFragmentList.add(longFragment);
mFragmentList.add(shortFragment);
mViewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
} @Override
public int getCount() {
return mFragmentList.size();
}
});
mTabs.setupWithViewPager(mViewPager);

上面是非常常见的一段代码,主要逻辑是,将承载两个Fragment的ViewPager与TabLayout同步起来。

其中,核心语句是:

	mTabs.setupWithViewPager(mViewPager);

3.2 查看 TabLayout 的相关源码

进入源码查看到:

	public void setupWithViewPager(@Nullable final ViewPager viewPager) {
if (mViewPager != null && mPageChangeListener != null) {
// If we've already been setup with a ViewPager, remove us from it
mViewPager.removeOnPageChangeListener(mPageChangeListener);
} if (viewPager != null) {
final PagerAdapter adapter = viewPager.getAdapter();
if (adapter == null) {
throw new IllegalArgumentException("ViewPager does not have a PagerAdapter set");
} mViewPager = viewPager; // Add our custom OnPageChangeListener to the ViewPager
if (mPageChangeListener == null) {
mPageChangeListener = new TabLayoutOnPageChangeListener(this);
}
mPageChangeListener.reset();
viewPager.addOnPageChangeListener(mPageChangeListener); // Now we'll add a tab selected listener to set ViewPager's current item
setOnTabSelectedListener(new ViewPagerOnTabSelectedListener(viewPager)); // Now we'll populate ourselves from the pager adapter
setPagerAdapter(adapter, true);
} else {
// We've been given a null ViewPager so we need to clear out the internal state,
// listeners and observers
mViewPager = null;
setOnTabSelectedListener(null);
setPagerAdapter(null, true);
}
}

也比较明了,无非是先做一系列的判断,然后修改 TabLayout与ViewPager的各种监听事件。

进入 setPagerAdapter 查看到如下方法:

	private void setPagerAdapter(@Nullable final PagerAdapter adapter, final boolean addObserver) {
if (mPagerAdapter != null && mPagerAdapterObserver != null) {
// If we already have a PagerAdapter, unregister our observer
mPagerAdapter.unregisterDataSetObserver(mPagerAdapterObserver);
} mPagerAdapter = adapter; if (addObserver && adapter != null) {
// Register our observer on the new adapter
if (mPagerAdapterObserver == null) {
mPagerAdapterObserver = new PagerAdapterObserver();
}
adapter.registerDataSetObserver(mPagerAdapterObserver);
} // Finally make sure we reflect the new adapter
populateFromPagerAdapter();
}

该方法的主要功能是设置TabLayout的适配器,populateFromPagerAdapter();方法引人注目。

	private void populateFromPagerAdapter() {
removeAllTabs(); if (mPagerAdapter != null) {
final int adapterCount = mPagerAdapter.getCount();
for (int i = 0; i < adapterCount; i++) {
// 从 PagerAdapter 中获取到标题,并新建 Tab 加入到空的 TabLayout 中
addTab(newTab().setText(mPagerAdapter.getPageTitle(i)), false);
} // Make sure we reflect the currently set ViewPager item
if (mViewPager != null && adapterCount > 0) {
final int curItem = mViewPager.getCurrentItem();
if (curItem != getSelectedTabPosition() && curItem < getTabCount()) {
selectTab(getTabAt(curItem));
}
}
} else {
removeAllTabs();
}
}

该方法中removeAllTabs();将所有的Tabs移除了,找到问题的关键!

同时,addTab(newTab().setText(mPagerAdapter.getPageTitle(i)), false);给了我们答案。

3.4 跳转到 PagerAdapter 的源码

再仔细看看 getPageTitle 这个方法:

	public CharSequence getPageTitle(int position) {
return null;
}

所以,知道为什么为空了吧!

3.4 结论

综上,mTabs.setupWithViewPager(mViewPager);语句的功能是:

  • 将 TabLayout、ViewPager 的监听事件同步
  • 对 TabLayout 的适配器进行重置
  • 对 TabLayout 的 TabItem 进行重置
  • 从 ViewPager 的 Adapter 中读取到每一页的标题,并为之创建 TabItem 添加到 TabLayout 中

3.5 解决方案

重写 getPageTitle 方法:

	mViewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
} @Override
public int getCount() {
return mFragmentList.size();
} @Override
public CharSequence getPageTitle(int position) {
return mTitle[position];
}
});

此文在我的 Github Pages 上同步发布,地址为:TabLayout与ViewPager同步后Tab的标题不显示

TabLayout与ViewPager同步后Tab的标题不显示的更多相关文章

  1. TabLayout+Fragment+ViewPager+FragmentStatePagerAdapter实现Tab标签

    首先来看下实现的效果吧: 最近在项目中实现这个效果的时候.尽管自己磕磕绊绊的实现了,可是知识确实模模糊糊的,今天天气异常的冷,在加上这个知识不太熟练,实在是没有心情进行接下来的计划,干脆借着这个时间, ...

  2. TabLayout:另一种Tab的实现方式

    http://blog.csdn.NET/aigestudio/article/details/47155769 在5.0以前我们想要实现像网易新闻客户端那样的的Tab可以有很多种选择: 比如古老的T ...

  3. TabLayout和ViewPager

    这里就说下tablayout+viewpager的实现方式:tablayout是android5.0推出来的一个MaterialDesign风格的控件,是专门用来实现tab栏效果的:功能强大,使用方便 ...

  4. TabLayout和ViewPager简单实现页卡的滑动

    首先需要在当前的module中的build Gradle的 dependencies中加入以下句子 compile 'com.android.support:design:23.0.1' 因为我们用到 ...

  5. TabLayout和ViewPager联动时的问题及解决方案

    问题概述 TabLayout搭配ViewPager关联使用时,在未调用TabLayout的setupWithViewPager(mViewPager)方法之前,ViewPager的内容和TabLayo ...

  6. Android两种为ViewPager+Fragment添加Tab的方式

    在Android开发中ViewPager的使用是非常广泛的,而它不仅仅能够实现简单的开始引导页,还可以结合Fragment并添加Tab作为选项卡或为显示大批量页面实现强大的顺畅滑动 下面介绍两种为Vi ...

  7. 关于TabLayout与ViewPager在Fragment中嵌套Fragment使用或配合使用的思考

    注意: 因为继承的是Fragment,所以getSupportFragmentManager()与getFragmentManager()方法无法使用,这里需要用到getChildFragmentMa ...

  8. Android 使用TabLayout、ViewPager和Fragment实现顶部菜单可滑动切换

    效果图如下 首先,要使用控件需要添加design library,在Android Studio中添加 compile 'com.android.support:design:23.4.0' 然后是布 ...

  9. 巧力避免ViewPager的预加载数据,Tablayout+Fragment+viewPager

    问题描述 最近在进行一个项目的开发,其中使用到了Tablayout+Fragment+viewPager来搭建一个基本的框架,从而出现了设置数据适配器的时候,item的位置错乱问题.我打印log日志的 ...

随机推荐

  1. MySQL Error: PROCEDURE xmdk.query_all_plan can't return a result set in the given context

    C++调用存储过程失败!出现如下错误:MySQL Error: PROCEDURE xmdk.query_all_plan can't return a result set in the given ...

  2. WPF进阶之接口(4):ICommand实现详解

    上一章WPF进阶之接口():INotifyPropertyChanged,ICommand中我们遗留了几个问题,我将在本节中做出解释.在详细解释ICommand实现之前,我们现在关注一下什么是:弱引用 ...

  3. ios开发之 -- 5分钟集成融云的客服功能

    最近项目中遇到了客服的功能,首先想到的就是使用融云的功能,因为以前做的即时通讯的项目,用的都是融云的sdk,花了点时间研究了下,希望能帮到大家! 废话不多说,步骤如下: 一.申请融云账号 二.创建应用 ...

  4. 创建4个线程,两个对j加一,两个对j减一(j两同两内)

    package multithread; public class MyThread { //j变量私有 private int j; //同步的+1方法 private synchronized v ...

  5. Hibernate传递list参数的例子

    public Map<String, String> getAllFeedBack(Object[] obj){ Map<String, String> map = new H ...

  6. 探讨Java I/O类和接口

    (输出)Output:程序---->数据源(如某个文件) (输入)Input:数据源---->程序 Java.io定义的I/O类如下表所示: BufferedInputStream Buf ...

  7. idea下maven项目增加依赖项目里面没有添加相关依赖jar

    困扰了一晚上的问题,一般在pom.xml中增加了相关依赖,idea会自动将依赖的Jar包增加到maven项目中,但是在pom.xml中增加了依赖,项目中并没有 偶然打开idea的侧边栏maven工具栏 ...

  8. Servlet------>jsp自定义标签2(让标签体不显示)

    自定义标签能做什么: 1.移除java代码 2.控制jsp页面某一部分是否执行 3.控制整个jsp是否执行 3.jsp内容重复输出 4.修改jsp内容输出 2.控制jsp页面某一部分是否执行 tag1 ...

  9. [linux基础学习]默认的目录介绍

    以下用一个表格来罗列linux默认的目录或文件及其用途: 目录/文件 用途 来源 / /处于Linux文件系统树形结构的最顶端,它是Linux文件系统的入口,所有的目录.文件.设备都在/之下. - / ...

  10. swift 下storyboard的页面跳转和传值

    ------------------1. 最简单的方法 拖拽, 这个就不用多解释了吧. 直接拖拽到另一个视图控制器, 选择 show, 就行了. 2. 利用 Segue 方法 (这里主要是 方法1 的 ...