美文网首页
TabLayout高级-自定义Indicator

TabLayout高级-自定义Indicator

作者: Zc0716 | 来源:发表于2018-03-25 10:36 被阅读0次

    一、问题背景

    在我们实际卡法需求中可能会要修改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

          本文链接:https://www.haomeiwen.com/subject/zalhcftx.html