玩转ViewPager系列(三)结合源码分析自定义tab不显示的问题

一.神奇的setupWithViewPager()方法

上一篇我们实现了tablayout和viewpager的绑定,只需要用 tabLayout.setupWithViewPager(viewPager) 这一句话就可以。那么这句话问什么如此神奇呢?我们来源码看看。

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();
            if (adapter != null) {
                this.setPagerAdapter(adapter, autoRefresh);
            }

            if (this.adapterChangeListener == null) {
                this.adapterChangeListener = new TabLayout.AdapterChangeListener();
            }

            this.adapterChangeListener.setAutoRefresh(autoRefresh);
            viewPager.addOnAdapterChangeListener(this.adapterChangeListener);
            this.setScrollPosition(viewPager.getCurrentItem(), 0.0F, true);
        } else {
            this.viewPager = null;
            this.setPagerAdapter((PagerAdapter)null, false);
        }

        this.setupViewPagerImplicitly = implicitSetup;
    }

这个方法重载了三次,最终都会调用到上面的方法。我们抛开一些判断不看,重点看下面这几行
在这里插入图片描述
我们在第一篇里给viewpager用匿名内部类的方式实现了OnPageChangeListener接口,而这里OnPageChangeListener接口的实现类则是TabLayoutTabLayoutOnPageChangeListener ,在这个类里面对tablayout进行一些操作。这样就实现了viewpager翻页滑动的时候,tablayout随之变化。

而下面这两句 this.currentVpSelectedListener = new TabLayout.ViewPagerOnTabSelectedListener(viewPager);
this.addOnTabSelectedListener(this.currentVpSelectedListener);
则是给tablayout自身加监听,用来监听选中的tab。我们看看ViewPagerOnTabSelectedListener的源码
在这里插入图片描述
我们在这里发现了viewpager!通过 this.viewPager.setCurrentItem(tab.getPosition()); 方法,实现了tab变化的时候,viewpager随之变化。

综上所述,在不需要自定义逻辑的时候,只调用tabLayout.setupWithViewPager(viewPager) 这个方法,即可实现联动,别人已经帮我们写好了,真的是很方便。

二.我们继续来看,为什么自定义tab样式时,tab会不显示呢?

如果我们在xml里设置自定义tab,或者通过代码设置的时候,写在tabLayout.setupWithViewPager(viewPager)方法之前,就会出现自定义无效的问题。我们结合源码看下,还是刚才的setupWithViewPager()方法
在这里插入图片描述
我们注意到,在tablayout和viewpager双向绑定之后,会调用这个方法。我们来看这个方法是什么。

在这里插入图片描述
首先,他会注册观察者,关于adapter的观察者模式,可以自行研究,这里不是重点。重点在下一句populateFromPagerAdapter()。我们再来看这个方法。
在这里插入图片描述
我们看到,首先他会清空所有的tab。这下明白为什么我们之前写的自定义样式都显示不出来了吧。接着他会根据viewpager里面的child个数,来对应的创建新的tab。在这个过程中,他会默认给tab加标题,这个标题就是我们在adapter里面重写的方法getpagetitle

  @Nullable
    @Override
    public CharSequence getPageTitle(int position) {
        return super.getPageTitle(position);
    }

本人总结的解决自定义tab不显示的方案(1)不用系统给的setupviewpager方法,自己去绑定(2)通过代码动态设置自定义的tab,写在setupWithViewPager后面,并且不要新建tab,而是通过tabLayout.getTabAt(i); 找到已经创建好的tab。

发布了4 篇原创文章 · 获赞 2 · 访问量 74

猜你喜欢

转载自blog.csdn.net/qq_39678305/article/details/104209037
今日推荐