TabLayout配合ViewPager来做Tab切换是常用的方式。但是有时我们会发现,在调用了android.support.design.widget.TabLayout#setupWithViewPager(android.support.v4.view.ViewPager, boolean, boolean)后,TabLayout的tab反而不显示标题了。
如何解决
需要重写ViewPager的PagerAdapter的android.support.v4.view.PagerAdapter#getPageTitle方法。
原因分析
所有的一切都发生在TabLayout和ViewPager的绑定时。我们来查看setupWithViewPager的源码。有多个重载方法。最终是调用这个。
private void setupWithViewPager(@Nullable ViewPager viewPager, boolean autoRefresh, boolean implicitSetup) {
if (this.viewPager != null) {
if (this.pageChangeListener != null) {
this.viewPager.removeOnPageChangeListener(this.pageChangeListener);
}
if (this.adapterChangeListener != null) {
this.viewPager.removeOnAdapterChangeListener(this.adapterChangeListener);
}
}
if (this.currentVpSelectedListener != null) {
this.removeOnTabSelectedListener(this.currentVpSelectedListener);
this.currentVpSelectedListener = null;
}
if (viewPager != null) {
this.viewPager = viewPager;
if (this.pageChangeListener == null) {
this.pageChangeListener = new TabLayout.TabLayoutOnPageChangeListener(this);
}
this.pageChangeListener.reset();
viewPager.addOnPageChangeListener(this.pageChangeListener);
this.currentVpSelectedListener = new TabLayout.ViewPagerOnTabSelectedListener(viewPager);
this.addOnTabSelectedListener(this.currentVpSelectedListener);
PagerAdapter adapter = viewPager.getAdapter();
重点1---------------------------------------------------
if (adapter != null) {
this.setPagerAdapter(adapter, autoRefresh);
}
if (this.adapterChangeListener == null) {
this.adapterChangeListener = new TabLayout.AdapterChangeListener();
}
this.adapterChangeListener.setAutoRefresh(autoRefresh);
重点2----------------------------------------------------------
viewPager.addOnAdapterChangeListener(this.adapterChangeListener);
this.setScrollPosition(viewPager.getCurrentItem(), 0.0F, true);
} else {
this.viewPager = null;
this.setPagerAdapter((PagerAdapter)null, false);
}
this.setupViewPagerImplicitly = implicitSetup;
}
我们先来看重点1,这时是直接把ViewPager的PagerAdapter取过来,通过android.support.design.widget.TabLayout#setPagerAdapter设置到TabLayout自己身上。
void setPagerAdapter(@Nullable PagerAdapter adapter, boolean addObserver) {
if (this.pagerAdapter != null && this.pagerAdapterObserver != null) {
this.pagerAdapter.unregisterDataSetObserver(this.pagerAdapterObserver);
}
this.pagerAdapter = adapter;
if (addObserver && adapter != null) {
if (this.pagerAdapterObserver == null) {
this.pagerAdapterObserver = new TabLayout.PagerAdapterObserver();
}
adapter.registerDataSetObserver(this.pagerAdapterObserver);
}
this.populateFromPagerAdapter();
}
设置之后又调用android.support.design.widget.TabLayout#populateFromPagerAdapter
void populateFromPagerAdapter() {
this.removeAllTabs();
if (this.pagerAdapter != null) {
int adapterCount = this.pagerAdapter.getCount();
int curItem;
for(curItem = 0; curItem < adapterCount; ++curItem) {
重点3-----------------------------------------------------
this.addTab(this.newTab().setText(this.pagerAdapter.getPageTitle(curItem)), false);
}
if (this.viewPager != null && adapterCount > 0) {
curItem = this.viewPager.getCurrentItem();
if (curItem != this.getSelectedTabPosition() && curItem < this.getTabCount()) {
this.selectTab(this.getTabAt(curItem));
}
}
}
}
在这个方法中清空了所有的tabs,然后又重新add,重点3的代码。是从pageAdapter中的android.support.v4.view.PagerAdapter#getPageTitle取到新的title。
有同学可能会说如果我在android.support.design.widget.TabLayout#setupWithViewPager(android.support.v4.view.ViewPager)调用之后再给ViewPager设置Adapter是不是就可以呢。答案是否定的,请看前面的重点2,
viewPager.addOnAdapterChangeListener(this.adapterChangeListener);
在setupWithViewPager时,会给ViewPager添加一个OnAdapterChangeListener(如果已经有的话,会先移除,注意看前边的代码),我们来查看一下它的实现。
if (this.adapterChangeListener == null) {
this.adapterChangeListener = new TabLayout.AdapterChangeListener();
}
向后追踪
private class AdapterChangeListener implements OnAdapterChangeListener {
private boolean autoRefresh;
AdapterChangeListener() {
}
public void onAdapterChanged(@NonNull ViewPager viewPager, @Nullable PagerAdapter oldAdapter, @Nullable PagerAdapter newAdapter) {
if (TabLayout.this.viewPager == viewPager) {
重点4-----------------------------------------------
TabLayout.this.setPagerAdapter(newAdapter, this.autoRefresh);
}
}
void setAutoRefresh(boolean autoRefresh) {
this.autoRefresh = autoRefresh;
}
}
重点4所示,最后在ViewPager的Adapter变化时,还是会调用 android.support.design.widget.TabLayout#setPagerAdapter。











网友评论