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显示不出来