TabLayout高级-自定义Indicator

一、问题背景 【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; } }

    推荐阅读