一、概述

1.1 问题描述

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

1.2 截图

二、结论

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

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

解决方案是:

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

  1. mViewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
  2. @Override
  3. public Fragment getItem(int position) {
  4. return mFragmentList.get(position);
  5. }
  6. @Override
  7. public int getCount() {
  8. return mFragmentList.size();
  9. }
  10. @Override
  11. public CharSequence getPageTitle(int position) {
  12. return mTitle[position];
  13. }
  14. });

三、问题探究

3.1 设置的代码

  1. mFragmentList.add(longFragment);
  2. mFragmentList.add(shortFragment);
  3. mViewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
  4. @Override
  5. public Fragment getItem(int position) {
  6. return mFragmentList.get(position);
  7. }
  8. @Override
  9. public int getCount() {
  10. return mFragmentList.size();
  11. }
  12. });
  13. mTabs.setupWithViewPager(mViewPager);

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

其中,核心语句是:

  1. mTabs.setupWithViewPager(mViewPager);

3.2 查看 TabLayout 的相关源码

进入源码查看到:

  1. public void setupWithViewPager(@Nullable final ViewPager viewPager) {
  2. if (mViewPager != null && mPageChangeListener != null) {
  3. // If we've already been setup with a ViewPager, remove us from it
  4. mViewPager.removeOnPageChangeListener(mPageChangeListener);
  5. }
  6. if (viewPager != null) {
  7. final PagerAdapter adapter = viewPager.getAdapter();
  8. if (adapter == null) {
  9. throw new IllegalArgumentException("ViewPager does not have a PagerAdapter set");
  10. }
  11. mViewPager = viewPager;
  12. // Add our custom OnPageChangeListener to the ViewPager
  13. if (mPageChangeListener == null) {
  14. mPageChangeListener = new TabLayoutOnPageChangeListener(this);
  15. }
  16. mPageChangeListener.reset();
  17. viewPager.addOnPageChangeListener(mPageChangeListener);
  18. // Now we'll add a tab selected listener to set ViewPager's current item
  19. setOnTabSelectedListener(new ViewPagerOnTabSelectedListener(viewPager));
  20. // Now we'll populate ourselves from the pager adapter
  21. setPagerAdapter(adapter, true);
  22. } else {
  23. // We've been given a null ViewPager so we need to clear out the internal state,
  24. // listeners and observers
  25. mViewPager = null;
  26. setOnTabSelectedListener(null);
  27. setPagerAdapter(null, true);
  28. }
  29. }

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

进入 setPagerAdapter 查看到如下方法:

  1. private void setPagerAdapter(@Nullable final PagerAdapter adapter, final boolean addObserver) {
  2. if (mPagerAdapter != null && mPagerAdapterObserver != null) {
  3. // If we already have a PagerAdapter, unregister our observer
  4. mPagerAdapter.unregisterDataSetObserver(mPagerAdapterObserver);
  5. }
  6. mPagerAdapter = adapter;
  7. if (addObserver && adapter != null) {
  8. // Register our observer on the new adapter
  9. if (mPagerAdapterObserver == null) {
  10. mPagerAdapterObserver = new PagerAdapterObserver();
  11. }
  12. adapter.registerDataSetObserver(mPagerAdapterObserver);
  13. }
  14. // Finally make sure we reflect the new adapter
  15. populateFromPagerAdapter();
  16. }

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

  1. private void populateFromPagerAdapter() {
  2. removeAllTabs();
  3. if (mPagerAdapter != null) {
  4. final int adapterCount = mPagerAdapter.getCount();
  5. for (int i = 0; i < adapterCount; i++) {
  6. // 从 PagerAdapter 中获取到标题,并新建 Tab 加入到空的 TabLayout 中
  7. addTab(newTab().setText(mPagerAdapter.getPageTitle(i)), false);
  8. }
  9. // Make sure we reflect the currently set ViewPager item
  10. if (mViewPager != null && adapterCount > 0) {
  11. final int curItem = mViewPager.getCurrentItem();
  12. if (curItem != getSelectedTabPosition() && curItem < getTabCount()) {
  13. selectTab(getTabAt(curItem));
  14. }
  15. }
  16. } else {
  17. removeAllTabs();
  18. }
  19. }

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

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

3.4 跳转到 PagerAdapter 的源码

再仔细看看 getPageTitle 这个方法:

  1. public CharSequence getPageTitle(int position) {
  2. return null;
  3. }

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

3.4 结论

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

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

3.5 解决方案

重写 getPageTitle 方法:

  1. mViewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
  2. @Override
  3. public Fragment getItem(int position) {
  4. return mFragmentList.get(position);
  5. }
  6. @Override
  7. public int getCount() {
  8. return mFragmentList.size();
  9. }
  10. @Override
  11. public CharSequence getPageTitle(int position) {
  12. return mTitle[position];
  13. }
  14. });

此文在我的 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. jQuery实现鼠标悬停显示提示信息窗口的方法

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. WebApi(6) 后台C#调用WebApi

    https://www.cnblogs.com/cxd1008/p/6640015.html 今天来写一下后台C#代码如何访问webapi 这里使用HttpClient方法访问webapi也是很常用的 ...

  3. Unreal新建C++类或C++项目失败

    出现以下错误: ... UnrealBuildTool Exception: System.UnauthorizedAccessException.... ... 是C盘无法访问权限的错误,请参考上一 ...

  4. 【黑金原创教程】【TimeQuest】【第二章】TimeQuest模型角色,网表概念,时序报告

    声明:本文为黑金动力社区(http://www.heijin.org)原创教程,如需转载请注明出处,谢谢! 黑金动力社区2013年原创教程连载计划: http://www.cnblogs.com/al ...

  5. Eclipse启动Server报错:Could not publish to the server. java.lang.NullPointerException

    转载自:http://m.blog.csdn.net/article/details?id=49862243 错误信息: publishing to tomcat v8.0 server at loc ...

  6. ERROR in [copy-webpack-plugin] unable to locate "D:/xxx/xxx/xxx"

    vue打包的时候npm run build报错 ERROR in [copy-webpack-plugin] unable to locate "D:/xxx/xxx/xxx" 这 ...

  7. JAVA需要掌握的一些技术

    1.你需要精通面向对象分析与设计(OOA/OOD).涉及模式(GOF,J2EEDP)以及综合模式.你应该了解UML,尤其是class,object,interaction以及statediagrams ...

  8. Tomcat上进行项目部署与WAR包含义

    一.WAR包 1.与JAR包类似,是将java类(编译好的.class)和Web资源,压缩后生成压缩包. 2. 与JAR相比,多了WEB-INF文件夹,其它多出来的内容基本都是Web资源 WEB-IN ...

  9. Windows MFC 打开文本

    MFC的CFileDialog自动封装了文件相关的对话框,提供一种简单的文件打开和文件存盘对话框功能. 要使用CFileDialog类,首先要构造一个对象, 项目实例: CFileDialog fil ...

  10. 全量日志 requestId

    常量参数和系统参数 API 的请求者不可见,由网关在请求后端服务时添加上. 常量参数.比如您的后端需要接收一个常量,但是这个常量您不希望被您的客户看见,那么就设置一个常量参数,可以在 Header 或 ...