一、概述
1.1 问题描述
TabLayout+ViewPager后,TabLayout的TabItem不显示的问题:
1.2 截图
二、结论
mTabs.setupWithViewPager(mViewPager);
语句的功能是:
- 将 TabLayout、ViewPager 的监听事件同步
- 对 TabLayout 的适配器进行重置
- 对 TabLayout 的 TabItem 进行重置
- 从 ViewPager 的 Adapter 中读取到每一页的标题,并为之创建 TabItem 添加到 TabLayout 中
解决方案是:
重写在 mViewPager 的 Adapter 中的如下方法,将每页的 Title 设置好:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 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 设置的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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同步起来。
其中,核心语句是:
1
| mTabs.setupWithViewPager(mViewPager);
|
3.2 查看 TabLayout 的相关源码
进入源码查看到:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| 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
查看到如下方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 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();
方法引人注目。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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);
给了我们答案。
再仔细看看 getPageTitle 这个方法:
1 2 3
| public CharSequence getPageTitle(int position) { return null; }
|
所以,知道为什么为空了吧!
3.4 结论
综上,mTabs.setupWithViewPager(mViewPager);
语句的功能是:
- 将 TabLayout、ViewPager 的监听事件同步
- 对 TabLayout 的适配器进行重置
- 对 TabLayout 的 TabItem 进行重置
- 从 ViewPager 的 Adapter 中读取到每一页的标题,并为之创建 TabItem 添加到 TabLayout 中
3.5 解决方案
重写 getPageTitle 方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 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]; } });
|