TabLayout高级-自定义Indicator

一、问题背景

在我们实际卡法需求中可能会要修改tablayout下方的indicator的样式与属性,比如indicator的长度,或者给tablayout加个背景但是需要indicator滑动的效果,然而原生的tablayout却仅仅提供了tablayout的height即厚度的属性,自定义化的程度很低。

二、问题探索

通过查阅源码,发现tablayout的下划线是由其内部类SlidingTabStrip实现,其继承自LinearLayout布局的viewgroup。源码如下

 private class SlidingTabStrip extends LinearLayout {
        private int mSelectedIndicatorHeight;
        private final Paint mSelectedIndicatorPaint;
        int mSelectedPosition = -1;
        float mSelectionOffset;
        private int mLayoutDirection = -1;
        private int mIndicatorLeft = -1;
        private int mIndicatorRight = -1;
        private ValueAnimator mIndicatorAnimator;
        SlidingTabStrip(Context context) {
            super(context);
            setWillNotDraw(false);
            mSelectedIndicatorPaint = new Paint();
        }
        ...
 @Override
 public void draw(Canvas canvas) {
   super.draw(canvas);
   // Thick colored underline below the current selection
   if (mIndicatorLeft >= 0 && mIndicatorRight > mIndicatorLeft) {
     canvas.drawRect(mIndicatorLeft, getHeight() - 
      mSelectedIndicatorHeight,mIndicatorRight, 
      getHeight(), mSelectedIndicatorPaint);
  }
}

省略部分细节代码,查看其ondraw方法会发现其绘制过程和三个变量相关:mSelectedIndicatorHeight,mIndicatorLeft 和mIndicatorRight ,由于mSelectedIndicatorHeight有提供接口可以改变可忽略,实际控制其绘制过程的为剩下俩个变量。

三、问题解决方案

正如上述缩分析的,控制SlidingTabStrip的绘制过程的为mIndicatorLeft 和mIndicatorRight 俩个变量,这俩个变量同时也是控制其位置显示的变量,只要获取到这俩个变量其实就可以进行我们自定义Indicator的封装,那么如何获取这俩个变量呢?——反射

//自定义drawable
public class IndicatorDrawable extends Drawable{
    View view;
    Paint paint;

    float paddingLeft;
    float paddingTop;

    public IndicatorDrawable(View view) {
        this.view = view;
        paint = new Paint();
        paint.setColor(Color.parseColor("#0f0"));
        float density = view.getResources().getDisplayMetrics().density;
        //这两个留白可以根据需求更改
        paddingLeft = 0 * density;
        paddingTop =  5 * density;
    }

    @Override
    public void draw(@NonNull Canvas canvas) {
        //自定义背景
        int mIndicatorLeft = getIntValue("mIndicatorLeft");
        int mIndicatorRight = getIntValue("mIndicatorRight");
        int height = view.getHeight();
        int radius = height / 2;
        if (mIndicatorLeft >= 0 && mIndicatorRight > mIndicatorLeft) {
            //canvas.drawRoundRect(new RectF(mIndicatorLeft + (int)paddingLeft, (int)paddingTop, mIndicatorRight - (int)paddingLeft, height - (int)paddingTop), radius, radius, paint);
            //缩减indicator的宽度    
            canvas.drawRect(mIndicatorLeft+40, height - 4,
                        mIndicatorRight-40, height, paint);
        }
    }

    int getIntValue(String name) {
        try {
            Field f = view.getClass().getDeclaredField(name);
            f.setAccessible(true);
            Object obj = f.get(view);
            return (Integer) obj;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return 0;
    }

    @Override
    public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {

    }

    @Override
    public void setColorFilter(@Nullable ColorFilter colorFilter) {

    }

    @Override
    public int getOpacity() {
        return PixelFormat.UNKNOWN;
    }
}

你可能感兴趣的:(TabLayout高级-自定义Indicator)