个人感觉Tablayout里的indicator左右滑动和摩拜单车里按钮背景左右滑动很像,所以我的思路是修改Tablayout里indicator的位置和形状,把indicator的位置放在tab下面,并且修改indicator的形状为圆角矩形,那接下来就是具体实现啦
我采用的方法是改写material design下TabLayout的源码,修改的地方只有两处,都位于TabLayout内部类
SlidingTabStrip 中
1、修改animateIndicatorToPosition()里的代码,这里主要处理按钮的背景左右移动的动画,
if (Math.abs(position - mSelectedPosition) <= 1) { // If the views are adjacent, we'll animate from edge-to-edge startLeft = mIndicatorLeft; startRight = mIndicatorRight; } else { // Else, we'll just grow from the nearest edge final int offset = dpToPx(MOTION_NON_ADJACENT_OFFSET); if (position < mSelectedPosition) { // We're going end-to-start if (isRtl) { startLeft = startRight = targetLeft - offset; } else { startLeft = startRight = targetRight + offset; } } else { // We're going start-to-end if (isRtl) { startLeft = startRight = targetRight + offset; } else { startLeft = startRight = targetLeft - offset; } } }
把以上这段代码浓缩成
startLeft = mIndicatorLeft; startRight = mIndicatorRight;
其余的都不要了
2.修改draw()方法里的代码,这里主要修改左右滑动背景的位置和形状
代码如下
@Override public void draw(Canvas canvas) { // Thick colored underline below the current selection if (mIndicatorLeft >= 0 && mIndicatorRight > mIndicatorLeft) { /*canvas.drawRect(mIndicatorLeft, getHeight() - mSelectedIndicatorHeight, mIndicatorRight, getHeight(), mSelectedIndicatorPaint);*/ int tabHeight=getChildAt(0).getHeight(); // getHeight()-tabHeight+10; RectF oval3 = new RectF(mIndicatorLeft+50, getHeight()-tabHeight+30, mIndicatorRight-50, getHeight()-30);// 设置个新的长方形 canvas.drawRoundRect(oval3, 60, 45, mSelectedIndicatorPaint); } super.draw(canvas); }
besides,mSelectedIndicatorPaint这个画笔必须加上抗锯齿属性
mSelectedIndicatorPaint.setAntiAlias(true);这样改完之后
setSelectedIndicatorHeight()设置indicator高度的方法就失效了,不过indicator的高度可以在draw里自己定义
来个效果图:
当然这种实现方法的缺点也有两个
1.要把tablayout以及相关类的源码复制出来,比较麻烦
2.无形中又多了好多个类啊,对APK大小敏感的同志慎用