自适应Tab宽度可以滑动文字逐渐变色的TabLayout

前言

TabLayout相信大家都用过,2015年Google大会上发布了新的Android Support Design库里面包含了很多新的控件,其中就包含TabLayout,它可以配合ViewPager完成很好的效果。

需求1

有时候会遇到这种需求,例如内涵段子(弱弱的问一句:有段友么?)。

像类似于上面一样,很有很多个tab,文字内容不固定,这时候使用TabLayout就会出现以下情况

我们会发现文字与文字之间隔的很远,需要设置tabPaddingStarttabPaddingEnd,但是布局填上去后发现并无卵用。。

需求2

一种类似于今日头条指示器,根据ViewPager的页面滑动,文字逐渐变色。详细效果请看TodayNews

ColorTrackTabLayout

先看下效果

源码

https://github.com/yewei02538/ColorTrackTabLayout

使用

因为是继承TabLayout,所以用法跟TabLayout一模一样

        //隐藏Indicator
        mTab.setSelectedTabIndicatorHeight(0);
        //设置左右内边距
        mTab.setTabPaddingLeftAndRight(10,10);
        mTab.setupWithViewPager(mViewPager);

原理

ColorTrackLayout主要是继承了TabLayout,对它做了一些扩展。滑动颜色渐变核心不懂的可以看下鸿洋大神的Android 自定义控件玩转字体变色 打造炫酷ViewPager指示器

既然是随着页面的滑动文字颜色渐变那么肯定少不了ViewPager的页面监听,这个在我们调用setupWithViewPager的时候TabLayout就已经添加监听。

    private void setupWithViewPager(@Nullable final ViewPager viewPager, boolean autoRefresh,
            boolean implicitSetup) {
        ....

        if (viewPager != null) {
            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
            mCurrentVpSelectedListener = new ViewPagerOnTabSelectedListener(viewPager);
            addOnTabSelectedListener(mCurrentVpSelectedListener);

            final PagerAdapter adapter = viewPager.getAdapter();
            if (adapter != null) {
                // Now we'll populate ourselves from the pager adapter, adding an observer if
                // autoRefresh is enabled
                setPagerAdapter(adapter, autoRefresh);
            }

            // Add a listener so that we're notified of any adapter changes
            if (mAdapterChangeListener == null) {
                mAdapterChangeListener = new AdapterChangeListener();
            }
            mAdapterChangeListener.setAutoRefresh(autoRefresh);
            viewPager.addOnAdapterChangeListener(mAdapterChangeListener);

            // Now update the scroll position to match the ViewPager's current item
            setScrollPosition(viewPager.getCurrentItem(), 0f, true);
        } else {
            // We've been given a null ViewPager so we need to clear out the internal state,
            // listeners and observers
            mViewPager = null;
            setPagerAdapter(null, false);
        }
        ....

    }

创建了mPageChangeListener并添加了监听
mPageChangeListener = new TabLayoutOnPageChangeListener(this);,所以我们必须要重写setupWithViewPager删除掉原来的监听,换成我们自己的监听

    @Override
    public void setupWithViewPager(@Nullable ViewPager viewPager, boolean autoRefresh) {
        super.setupWithViewPager(viewPager, autoRefresh);
        try {
            //通过反射找到mPageChangeListener
            Field field = TabLayout.class.getDeclaredField("mPageChangeListener");
            field.setAccessible(true);
            TabLayoutOnPageChangeListener listener = (TabLayoutOnPageChangeListener) field.get(this);
            if (listener != null) {
                //删除自带监听
                viewPager.removeOnPageChangeListener(listener);
                mPageChangeListenter = new ColorTrackTabLayoutOnPageChangeListener(this);
                mPageChangeListenter.reset();
                viewPager.addOnPageChangeListener(mPageChangeListenter);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

还需要做的一点就是把TabLayout每一个的Tab布局替换成我们的。怎么替换呢?重写addTab,在添加的时候改成我们的布局

    @Override
    public void addTab(@NonNull Tab tab, int position, boolean setSelected) {
        ColorTrackView colorTrackView = new ColorTrackView(getContext());
        colorTrackView.setProgress(setSelected ? 1 : 0);
        colorTrackView.setText(tab.getText() + "");
        colorTrackView.setTextSize(mTabTextSize);
        colorTrackView.setTag(position);
        colorTrackView.setTextChangeColor(mTabSelectedTextColor);
        colorTrackView.setTextOriginColor(mTabTextColor);
        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        colorTrackView.setLayoutParams(layoutParams);
        tab.setCustomView(colorTrackView);

        super.addTab(tab, position, setSelected);
        if (position == 0) {
            //默认选中第一个
            setSelectedView(position);
        }

        setTabWidth(position, colorTrackView);
    }

其关键就是将我们的布局利用setCustomView方法来设置上去。

最后

喜欢的话记得给个star哦~

鸣谢

ColorTrackView