通过Paint和Canvas绘制动态的打勾和打叉效果

效果

通过Paint和Canvas绘制动态的打勾和打叉效果

几个要点:

1. 坐标系以左上角为原点,横X竖Y

2. 笔刷Paint

Paint paint = new Paint();

//设置画笔颜色
paint.setColor(getResources().getColor(R.color.arc_fail_color));

//设置画笔的宽度
paint.setStrokeWidth(lineThick);

//设置图形为空心
paint.setStyle(Paint.Style.STROKE);

//消除锯齿
paint.setAntiAlias(true);

3. 绘制直线

/**   Canvas
 * Draw a line segment with the specified start and stop x,y coordinates,
 * using the specified paint.
 *
 * @param startX The x-coordinate of the start point of the line
 * @param startY The y-coordinate of the start point of the line
 * @param paint  The paint used to draw the line
 */
public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint)

 4. 绘制圆弧

/**
 * <p>Draw the specified arc, which will be scaled to fit inside the
 * specified oval.</p>
 *
 * <p>If the start angle is negative or >= 360, the start angle is treated
 * as start angle modulo 360.</p>
 *
 * <p>If the sweep angle is >= 360, then the oval is drawn
 * completely. Note that this differs slightly from SkPath::arcTo, which
 * treats the sweep angle modulo 360. If the sweep angle is negative,
 * the sweep angle is treated as sweep angle modulo 360</p>
 *
 * <p>The arc is drawn clockwise. An angle of 0 degrees correspond to the
 * geometric angle of 0 degrees (3 o'clock on a watch.)</p>
 *
 * @param oval       The bounds of oval used to define the shape and size
 *                   of the arc
 * @param startAngle Starting angle (in degrees) where the arc begins
 * @param sweepAngle Sweep angle (in degrees) measured clockwise
 * @param useCenter If true, include the center of the oval in the arc, and
                    close it if it is being stroked. This will draw a wedge
 * @param paint      The paint used to draw the arc
 */
public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)

 注:

以时钟三点为0度;

完整角度以360°来计算;

oval限定绘图区域

startAngle为起始角度;

sweepAngle表示划过的角度,如果为负值则逆时针画

useCenter如果为true则画出扇形效果,否则只有一个圆弧

RectF的初始化

/**
 * Create a new rectangle with the specified coordinates. Note: no range
 * checking is performed, so the caller must ensure that left <= right and
 * top <= bottom.
 *
 * @param left   The X coordinate of the left side of the rectangle
 * @param top    The Y coordinate of the top of the rectangle
 * @param right  The X coordinate of the right side of the rectangle
 * @param bottom The Y coordinate of the bottom of the rectangle
 */
public RectF(float left, float top, float right, float bottom)

5. 获取用户在xml中自定义的宽度值 layout_width

public DrawCrossMarkView(Context context, AttributeSet attrs) {
    super(context, attrs);

    Pattern p = Pattern.compile("\\d*");

    Matcher m = p.matcher(attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "layout_width"));

    if (m.find()) {
        totalWidth = Float.valueOf(m.group());
    }

    init();
} 

注:

在构造函数中通过getWidth来获取宽度得到的结果往往是0,在执行到onDraw的时候,控件大小才划定;

本例中默认用户以dp为单位设置layout_width。

6. 重写onDraw方法,在没有绘制完成前,通过postInvalidateDelayed定义重绘间隔,每一次重绘,之前绘制的图案都会被清除

//绘制
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    Log.w("check mark", "drawing... # progress=" + progress);

    if (progress < 100)
        progress+=step;

    //根据进度画圆弧
    canvas.drawArc(rectF, 235, -360 * progress / 100, false, paint);

    //先等圆弧画完,画叉
    if (progress >= 100) {
        if (line1X < maxLineIncrement) {
            line1X+=step;
            line1Y+=step;
        }

        //画第一根线
        canvas.drawLine(line1StartX, lineStartY, line1StartX - line1X, lineStartY + line1Y, paint);

        if (line1X >= maxLineIncrement) {

            line2X+=step;
            line2Y+=step;

            //画第二根线
            canvas.drawLine(line2StartX, lineStartY, line2StartX + line2X, lineStartY + line2Y, paint);
        }
    }

    //每隔6毫秒界面刷新
    if (line2X < maxLineIncrement)
        postInvalidateDelayed(6);
}

7. 调用

在布局文件中添加控件

<com.xuanzhui.animations.view.DrawCrossMarkView
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:layout_margin="50dp"/>

 在color总定义颜色

<color name="arc_fail_color">#D93549</color>

8. 完整代码见 https://github.com/xuanzhui/Animations

相关推荐