通常在ViewPager的上方,我们都会放一个标签指示器与ViewPager进行联动。tablayout作为官方退出的自带控件,大家应该都可以熟练使用了。面对各种需求,tablayout提供了几个简单的方法用来设置颜色,下划线宽度等。下面来完成几个自带方法不能解决的需求:
需求
1:缩短下划线宽度
2:自定义下划线样式,比如弯曲的线条,比tab文字宽度更窄
解决方法
网上有个很好的解决方案,可以用来设置下划线的宽度,是利用反射修改来达到目的:
public void setIndicator(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();
}
}
这是可以缩短下划线宽度,但是貌似宽度不能比tab文字宽度更小,但是需求是宽度要比文字还窄。为了可以继续使用tablayout,我们可以自定义一个指示器:
自定义指示器(Indicator)
大致思路:
1:设置tablayout自带指示器高度为0。
2:在tablayout底部放一个自定义的指示器view,比如背景一条横线的窄线条
3:利用tablayout和指示器的宽度计算调整指示器初始位置和第一个tab居中对其
4:监听viewpager的PageChangeListener,根据滑动时候的position和positionOffset动态修改指示器位置,达到滑动效果
代码示例:
tab.post(new Runnable() {
@Override
public void run() {
initMargin = tab.getWidth() / 4 / 2 - tabIndicator.getWidth() / 2;
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) tabIndicator.getLayoutParams();
params.leftMargin = initMargin;
tabIndicator.setLayoutParams(params);
}
});
获取初始margin值,使指示器和第一个tab居中对齐
tabWidth = tab.getWidth() / 4;
pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
params.leftMargin = (int) (tabWidth * positionOffset + tabWidth * position)+initMargin;
tabIndicator.setLayoutParams(params);
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
通过对viewpager的滑动监听动态修改margin值,达到滑动效果就ok了。