好久没有写自定义View相关的内容,好多东西都忘记干净了,乘着这有时间,赶紧复习下。渐渐发现,一些炫酷的view效果,通过需要自定义view和属性动画结合在一起,才能更容易的实现。
实现的效果图如下:
所用的知识有:
(1)自定义View中的 path ,主要用来绘制指示块。
(2)属性动画-ValueAnimator,并设置属性动画的监听器。
(3)根据属性动画是否结束的标志,决定是否绘制分数对应的描述文本内容。
实现步骤:
- 继承自View,在构造函数中获取自定义属性和初始化操作(初始化画笔)
private void obtainAttrs(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ScoreView);
lineLength = typedArray.getDimension(R.styleable.ScoreView_lineLength, dp2Px(10));
lineColor = typedArray.getColor(R.styleable.ScoreView_lineColor, Color.WHITE);
typedArray.recycle();
}
private void init() {
arrowPaint = createPaint(Color.WHITE, 0, Paint.Style.FILL, 0);
arcPaint = createPaint(lineColor, dp2Px(1), Paint.Style.STROKE, 0);
bgPaint = createPaint(lineColor, dp2Px(1), Paint.Style.FILL, 0);
reachProgressPaint = createPaint(Color.WHITE, dp2Px(1), Paint.Style.FILL, 0);
arcReachPaint = createPaint(Color.WHITE, dp2Px(1), Paint.Style.STROKE, 0);
scoreTextPaint = createPaint(Color.WHITE, 0, Paint.Style.STROKE, dp2Px(26));
descTextPaint = createPaint(Color.WHITE, 0, Paint.Style.STROKE, dp2Px(16));
}
其中初始化画笔抽取到一个函数中:
private Paint createPaint(int color, int strokeWidth, Paint.Style style, float textSize) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(color);
paint.setStrokeWidth(strokeWidth);
paint.setStyle(style);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setTextSize(textSize);
return paint;
}
- 覆盖 onSizeChanged() ,得到控件的宽高,并决定要绘制区域的大小(控件默认设置了内边距)
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
viewWidth = w;
viewHeight = h;
halfView = Math.min(viewWidth, viewHeight) / 2; //宽度或高度中最小值的一半,即决定圆心的位置。
radius = (Math.min(viewWidth, viewHeight) - 2 * DEFAULT_PADDING) / 2; //绘制园的半径是宽高除去默认内边距
}
- 核心绘制代码,覆盖onDraw()方法,根据动画是否结束的标志,决定是否绘制分数对应的文本。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawArcBackground(canvas);
drawArcProgress(canvas);
drawScoreText(canvas);
if (isAnimEnd) {
drawDescText(