自定义TabLayout

2020-03-21  本文已影响0人  dengbin

众所周知,TabLayout 特别好用,项目里面需要自定义Tab字体和Indicator

image

想到的方案有两个:

一是获取系统默认TabItem的TextView,然后动态设置字体和背景来实现,后来发现textSize属性不生效,app:tabTextAppearance 满足不了需求。

二是自定义View,即Tablayout.Tab.setCustomView()。写了demo,实现了需求。整理一下代码重写TabLayout,即插即用,打算后期丰富API,完善过渡动画等。

import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.Typeface;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.meishubao.client.R;

import java.util.ArrayList;
import java.util.List;

/**
 * @Description: 自定义顶部Tab导航
 * @Author: dengbin
 * @CreateDate: 2020/3/20 18:02
 * @UpdateUser: dengbin
 * @UpdateDate: 2020/3/20 18:02
 * @UpdateRemark: 更新说明
 */
public class MTabLayout extends TabLayout {

    // 所绑定的 ViewPager 的 Adapter
    private PagerAdapter pagerAdapter;
    // title 集合
    private int tmpTitleInitPos;
    private List<CharSequence> titleStringList = new ArrayList<>();
    // 监听 Adapter 数据变化
    private DataSetObserver dataSetObserver = new DataSetObserver() {
        @Override
        public void onChanged() {
            super.onChanged();
            updateTitleText();
        }

        @Override
        public void onInvalidated() {
            super.onInvalidated();
            updateTitleText();
        }
    };
    private ViewPager.OnPageChangeListener pageChangeListener = new ViewPager.OnPageChangeListener() {

        int currentPos; // 上一次选中的页面
        boolean posChanged; // 页面有所切换

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {
            Tab tab0 = getTabAt(arg0);
            Tab tab1 = getTabAt(arg0 + 1);
            animationTab(tab0, arg1);
            animationTab(tab1, 1f - arg1);
        }

        @Override
        public void onPageSelected(int i) {
            posChanged = i != currentPos;
            if (posChanged) {
                setTabText(getTabAt(currentPos), false);
                setTabText(getTabAt(i), true);
            }
            currentPos = i;
        }

        @Override
        public void onPageScrollStateChanged(int i) {
            if (i != ViewPager.SCROLL_STATE_IDLE || !posChanged)
                return;
            resetTab(currentPos);
        }
    };

    public MTabLayout(Context context) {
        this(context, null);
    }

    public MTabLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    // 重写该方法,实现 setCustomView
    @NonNull
    @Override
    public Tab newTab() {
        Tab tab = super.newTab();
        View view = LayoutInflater.from(getContext()).inflate(R.layout.item_gallery_tab, null);
        tab.setCustomView(view);
        if (titleStringList.size() > 0 && tmpTitleInitPos < titleStringList.size()) {
            CharSequence cs = titleStringList.get(tmpTitleInitPos++);
            TextView tv = view.findViewById(R.id.tab_tv);
            tv.setText(cs);
        }

        if (tmpTitleInitPos == 1) { // 初始化选中第一个
            setTabText(tab, true);
        }

        if (tmpTitleInitPos >= titleStringList.size()) {
            titleStringList.clear();
            tmpTitleInitPos = 0;
        }

        return tab;
    }

    @Override
    public void setupWithViewPager(@Nullable ViewPager viewPager) {
        super.setupWithViewPager(viewPager);
        if (viewPager == null)
            return;
        pagerAdapter = viewPager.getAdapter();
        if (pagerAdapter == null) {
            // 监听 ViewPager 的 Adapter 变化
            viewPager.addOnAdapterChangeListener((viewPager1, pagerAdapter, pagerAdapter1) -> {
                if (this.pagerAdapter != null)
                    this.pagerAdapter.unregisterDataSetObserver(dataSetObserver);
                this.pagerAdapter = pagerAdapter1;
                if (this.pagerAdapter != null)
                    registerDataSetObserver();
            });
        } else {
            registerDataSetObserver();
        }

        // 监听 ViewPager 滑动实现过渡效果
        viewPager.addOnPageChangeListener(pageChangeListener);
    }

    // 注册数据监听
    private void registerDataSetObserver() {
        pagerAdapter.registerDataSetObserver(dataSetObserver);
    }

    // 更新 title 文本,保存到集合
    private void updateTitleText() {
        int adapterCount = pagerAdapter.getCount();
        int curItem;
        for (curItem = 0; curItem < adapterCount; ++curItem) {
            CharSequence title = pagerAdapter.getPageTitle(curItem);
            titleStringList.add(TextUtils.isEmpty(title) ? "" : title);
        }
    }

    private void animationTab(Tab tab, float per) {
        if (tab == null || tab.getCustomView() == null)
            return;
        RelativeLayout rl = (RelativeLayout) tab.getCustomView();
        View view = rl.findViewById(R.id.tab_bg_view);
        view.setAlpha(1f - per);
    }

    private void setTabText(Tab tab, boolean selected) {

        animationTab(tab, selected ? 0f : 1f);

        if (tab == null || tab.getCustomView() == null)
            return;
        RelativeLayout rl = (RelativeLayout) tab.getCustomView();

        TextView tv = rl.findViewById(R.id.tab_tv);
        tv.setTypeface(Typeface.defaultFromStyle(selected ? Typeface.BOLD : Typeface.NORMAL));
        tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, selected ? 22f : 14f);
        tv.setTextColor(tv.getResources().getColor(selected ? R.color.msb_text_black : R.color.msb_text_gray));
    }

    private void resetTab(int currentPos) {
        for (int i = 0; i < getTabCount(); i++)
            setTabText(getTabAt(i), i == currentPos);
    }

}
上一篇下一篇

猜你喜欢

热点阅读