TabLayout的高级用法(自定义tab和修改指示器宽度)

TabLayout很好用,但是原生的属性很难满足正式的需求,所以就得自定义自己的tab(可以时单纯文字或者文图混排形式),原生的切换没有动画效果,为了交互效果好点我们也可以添加相应的动画,原生的tabIndicator只提供了设置高度和背景色的方法,宽度是均分的,有点丑;要实现以上需求,我准备了一个工具类,可以根据业务对其扩充或修改

/**
 * @Desc: 为TabLayout设置动画
 * @Author: JiangRongtao
 * @Created by: 2018/12/21 0021 13:55
 **/

public class TabLayoutAnimUtils {
    private TabLayout mTabLayout;
    private List<String> mTitleList;
    private Context mContext;

    public TabLayoutAnimUtils(Context context, TabLayout tabLayout, List<String> titleList) {

        this.mContext = context;
        this.mTabLayout = tabLayout;
        this.mTitleList = titleList;
    }

    /**
     * 设置每个TabLayout的自定义View
     * 注意:TabLayout和Viewpager配合使用的时候必须先mViewPager.setAdapter(),再初始化该方法,然后addOnTabSelectedListener;因为adapter刷新会让mCustomViewView空,
     */
    public void setCustomViews() {
        int mSelectedTabPosition = mTabLayout.getSelectedTabPosition();
        for (int i = 0; i < this.mTitleList.size(); i++) {
            TabLayout.Tab mTab = this.mTabLayout.getTabAt(i).setCustomView(getTabView(i, mSelectedTabPosition));
            if (i == mSelectedTabPosition) {
                changeTabSelect(mTab);
            } else {
                changeTabNormal(mTab);
            }
        }
    }

    /**
     * 提供TabLayout的View
     * 根据index返回不同的View
     * 主意:默认选中的View要返回选中状态的样式
     */
    private View getTabView(int index, int mSelectedTabPosition) {
        //自定义View布局
        View view = LayoutInflater.from(mContext).inflate(R.layout.custom_tab_item_layout, null);
        TextView title = (TextView) view.findViewById(R.id.title);
        title.setText(mTitleList.get(index));
        title.setSelected(index == mSelectedTabPosition ? true : false);
        return view;
    }

    /**
     * 改变TabLayout的View到选中状态
     * 使用属性动画改编Tab中View的状态
     */
    public void changeTabSelect(TabLayout.Tab tab) {
        final View view = tab.getCustomView();
        ObjectAnimator anim = ObjectAnimator
                .ofFloat(view, "", 1.0F, 1.1F)
                .setDuration(200);
        anim.start();
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float cVal = (Float) animation.getAnimatedValue();
                view.setAlpha(0.5f + (cVal - 1f) * (0.5f / 0.1f));
                view.setScaleX(cVal);
                view.setScaleY(cVal);
            }
        });
    }

    /**
     * 改变TabLayout的View到未选中状态
     */
    public void changeTabNormal(TabLayout.Tab tab) {
        final View view = tab.getCustomView();
        ObjectAnimator anim = ObjectAnimator
                .ofFloat(view, "", 1.0F, 0.9F)
                .setDuration(200);
        anim.start();
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float cVal = (Float) animation.getAnimatedValue();
                view.setAlpha(1f - (1f - cVal) * (0.5f / 0.1f));
                view.setScaleX(cVal);
                view.setScaleY(cVal);
            }
        });
    }

    /**
     * 改变tablayout指示器的宽度
     *
     * @param tabLayout
     * @param margin
     */
    public void changeTabIndicatorWidth(final TabLayout tabLayout, final int margin) {
        tabLayout.post(new Runnable() {
            @Override
            public void run() {
                try {
                    Field mTabStripField = tabLayout.getClass().getDeclaredField("mTabStrip");
                    mTabStripField.setAccessible(true);

                    LinearLayout mTabStrip = (LinearLayout) mTabStripField.get(tabLayout);

                    int dp10 = margin == 0 ? 50 : margin;

                    for (int i = 0; i < mTabStrip.getChildCount(); i++) {
                        View tabView = mTabStrip.getChildAt(i);

                        Field mTextViewField = tabView.getClass().getDeclaredField("mTextView");
                        mTextViewField.setAccessible(true);

                        TextView mTextView = (TextView) mTextViewField.get(tabView);

                        tabView.setPadding(0, 0, 0, 0);

                        int width = 0;
                        width = mTextView.getWidth();
                        if (width == 0) {
                            mTextView.measure(0, 0);
                            width = mTextView.getMeasuredWidth();
                        }

                        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) tabView.getLayoutParams();
                        params.width = width;
                        params.leftMargin = dp10;
                        params.rightMargin = dp10;
                        tabView.setLayoutParams(params);

                        tabView.invalidate();
                    }

                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public void changeTabIndicatorWidth(TabLayout tabLayout) {
        changeTabIndicatorWidth(tabLayout, 0);
    }

    /**
     * 设置tablayout指示器的宽度
     *
     * @param tabs
     * @param leftDip
     * @param rightDip
     */
    public void setIndicatorWidth(TabLayout tabs, int leftDip, int rightDip) {
        Class<?> tabLayout = tabs.getClass();
        Field tabStrip = null;
        try {
            tabStrip = tabLayout.getDeclaredField("mTabStrip");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }

        tabStrip.setAccessible(true);
        LinearLayout llTab = null;
        try {
            llTab = (LinearLayout) tabStrip.get(tabs);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        int left = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, leftDip, Resources.getSystem().getDisplayMetrics());
        int right = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, rightDip, Resources.getSystem().getDisplayMetrics());

        for (int i = 0; i < llTab.getChildCount(); i++) {
            View child = llTab.getChildAt(i);
            child.setPadding(0, 0, 0, 0);
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1);
            params.leftMargin = left;
            params.rightMargin = right;
            child.setLayoutParams(params);
            child.invalidate();
        }
    }

}

具体用法部分代码如下

 mViewPager.setAdapter(new TabPagerAdapter(getChildFragmentManager(), mFragmentList, mTitles));
        mTabLayout.setupWithViewPager(mViewPager);
        //设置自定义动画
        final TabLayoutAnimUtils mTabLayoutAnimUtils = new TabLayoutAnimUtils(mContext, mTabLayout, mTitles);
        mTabLayoutAnimUtils.changeTabIndicatorWidth(mTabLayout);
        mTabLayoutAnimUtils.setCustomViews();
        mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                mTabLayoutAnimUtils.changeTabSelect(tab);
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
                mTabLayoutAnimUtils.changeTabNormal(tab);
            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });

注意:TabLayout和Viewpager配合使用的时候必须先mViewPager.setAdapter(),再初始化该方法,然后addOnTabSelectedListener;因为adapter刷新会让mCustomView空,也就是你设置的mCustomView显示不出来

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值