美文网首页
自定义view,实现环形动画

自定义view,实现环形动画

作者: 糖糖_2c32 | 来源:发表于2019-05-20 17:37 被阅读0次

本文参考自https://www.jianshu.com/p/bc7bdaeb9eb2

思路:首先画一个最外面的圆,然后再画一可以旋转的弧形,最后画一中间的圆。

首先,在values中新建attrs.xml文件,文件中的内容为:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="BoxDrawingView">
        <attr name="ringWidth" format="dimension"/>
        <attr name="startAngle" format="integer"/>
        <attr name="endAngle" format="integer"/>
        <attr name="duation" format="integer"/>
        <attr name="bottomColor" format="color"/>
        <attr name="topColor" format="color"/>
        <attr name="centerColor" format="color"/>
        <attr name="textColor" format="color"/>
    </declare-styleable>
</resources>

此步骤和CircularView中的

 //TODO需要从attrs中获取参数
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BoxDrawingView);
        setBottomColor(a.getColor(R.styleable.BoxDrawingView_bottomColor, bottomColor));
        setTopColor(a.getColor(R.styleable.BoxDrawingView_topColor, topColor));
        setCenterColor(a.getColor(R.styleable.BoxDrawingView_centerColor, centerColor));

        setEndAngle(a.getInteger(R.styleable.BoxDrawingView_endAngle, endAngle));
        setStartAngle(a.getInteger(R.styleable.BoxDrawingView_startAngle, startAngle));
        setDuation(a.getInteger(R.styleable.BoxDrawingView_duation, duation));
        setRingWidth(a.getDimensionPixelOffset(R.styleable.BoxDrawingView_ringWidth, ringWidth));

        a.recycle();

相对照,为定义自定义view的属性,和android:layout_width="100dp";相类似

public class CircularView extends View {

    //底色的圆:最大圆
    private float bottomWidth = 200;
    private Paint bottomPaint;
    private int bottomColor = Color.GRAY;//底圆的颜色
    //上层的扇形
    private float topWidth;
    private Paint topPaint;
    private int topColor = Color.DKGRAY;//代表进度的扇形的颜色

    private int ringWidth = 20;//环形的宽度

    private int endAngle = 0;//上层圆环的着色,目标角度
    private int currentAngle = 0;//上层圆环的着色,当前角度
    private int startAngle = 180;//上层圆环的着色,开始角度

    //中间圆
    private int centerColor = Color.WHITE;//圆环中间的颜色
    private Paint centerPaint;

    boolean isFirst = true;
    boolean isDrawText = true;

    private int duation = 2000;//动画的事件长度

    public CircularView(Context context) {
        super(context);
    }

    public CircularView(Context context, AttributeSet attrs) {
        super(context, attrs);
        //初始化画笔
        topPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        bottomPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        centerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        //TODO需要从attrs中获取参数
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BoxDrawingView);
        setBottomColor(a.getColor(R.styleable.BoxDrawingView_bottomColor, bottomColor));
        setTopColor(a.getColor(R.styleable.BoxDrawingView_topColor, topColor));
        setCenterColor(a.getColor(R.styleable.BoxDrawingView_centerColor, centerColor));

        setEndAngle(a.getInteger(R.styleable.BoxDrawingView_endAngle, endAngle));
        setStartAngle(a.getInteger(R.styleable.BoxDrawingView_startAngle, startAngle));
        setDuation(a.getInteger(R.styleable.BoxDrawingView_duation, duation));
        setRingWidth(a.getDimensionPixelOffset(R.styleable.BoxDrawingView_ringWidth, ringWidth));

        a.recycle();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (isFirst) {
            isFirst = false;
            topWidth = getWidth();
            bottomWidth = getWidth();
            drawBottom(canvas);
            drawTop(canvas);
            drawCenter(canvas);
            startAnimation();
        } else {
            drawBottom(canvas);
            drawTop(canvas);
            drawCenter(canvas);
        }

    }

    protected void drawBottom(Canvas canvas) {
        //画底部的圆
        bottomPaint.setColor(bottomColor);
        canvas.drawCircle(getWidth() / 2, getHeight() / 2, bottomWidth / 2, bottomPaint);
    }

    protected void drawTop(Canvas canvas) {
        //画出中间的着色扇形
        topPaint.setColor(topColor);
        RectF rectF = new RectF(0, 0, getWidth(), getWidth());
        canvas.drawArc(rectF, startAngle, currentAngle, true, topPaint);

    }

    protected void drawCenter(Canvas canvas) {
        //画出最中间的圆
        centerPaint.setColor(centerColor);
        canvas.drawCircle(getWidth() / 2, getHeight() / 2, (topWidth - ringWidth * 2) / 2, centerPaint);

    }

    private void startAnimation() {
        ValueAnimator animator = ValueAnimator.ofInt(0, endAngle);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                currentAngle = (int) animation.getAnimatedValue();
                invalidate();
            }
        });
        animator.setDuration(duation);
        animator.start();
    }

    //设置最终扇形的角度
    public void setEndAngle(int angle) {
        this.endAngle = angle;
    }

    //设置开始的角度
    public void setStartAngle(int startAngle) {
        this.startAngle = startAngle;
    }

    //设置动画时常
    public void setDuation(int duation) {
        this.duation = duation;
    }

    //设置圆环的宽度
    public void setRingWidth(int ringWidth) {
        this.ringWidth = ringWidth;
    }

    //设置进度条的颜色
    public void setTopColor(int topColor) {
        this.topColor = topColor;
    }

    //设置中间小圆的颜色
    public void setCenterColor(int centerColor) {
        this.centerColor = centerColor;
    }

    //设置底圆的颜色
    public void setBottomColor(int bottomColor) {
        this.bottomColor = bottomColor;
    }

    //刷新View
    public void refresh() {
        startAnimation();
    }
}

使用

<FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:layout_alignParentEnd="true"
            android:layout_margin="16sp">

            <com.bignerdranch.android.fardimension.view.CircularView
                android:id="@+id/marking_view"
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:layout_gravity="center"
                app:bottomColor="#fffae3"
                app:ringWidth="8dp"
                app:topColor="#58564c"  />

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginBottom="10dp"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/tv"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="0"
                    android:textColor="#506946"
                    android:textSize="32sp" />

            </LinearLayout>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginTop="20dp"
                android:text="分数"
                android:textColor="#CFD5DE"
                android:textSize="16sp" />

        </FrameLayout>

在activity中的使用,其中score可以替换为0-100中的任意数字

//设置环形进度条的参数
circularView.setEndAngle((int) (360 * (score / 100f)));
circularView.setStartAngle(270);
circularView.setDuation(2000);
circularView.refresh();

相关文章

网友评论

      本文标题:自定义view,实现环形动画

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