仿小米文件 加载Loading

该文详细描述了如何在Android中使用canvas和ValueAnimator创建一个外部圆圈内含一个做圆周运动的小圆的动画效果。通过drawArc绘制外圆,利用三角函数计算内圆在特定旋转角度下的坐标,然后用ValueAnimator进行动画更新,实现内圆的持续旋转。此外,还提到了通过旋转画布的简化实现方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先看效果如下:

拆分需求: 外部有一个圆圈 内部一个圆切着内圆做圆周运动

首先绘制外圆圈,我是直接绘制一个圆弧

   canvas.drawArc( left,  top,  right,  bottom, 0,
        360,false,outCircle);

绘制内部圆圈,因为内部圆是切着外圆运动的所以需要用到三角函数知识,当前的内圆旋转角度是已知的,圆的半径也是已知,计算当前点的x,y

  float x = (float) (Math.sin(rotateAngle) * (circle - strokeWidth/2 - inCircularR-30) );

   float y = (float) (Math.cos(rotateAngle)*(circle - strokeWidth/2- inCircularR-30));
   //绘制内置圆圈
   canvas.drawCircle(circle+x,circle+y,inCircularR,inCircular);

然后添加数值动画,使其动起来

 valueAnimator = ValueAnimator.ofFloat(1);
        valueAnimator.setDuration(100000);
        valueAnimator.setRepeatCount(-1);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float progress = (float) animation.getAnimatedValue();
                Log.d(TAG, "onAnimationUpdate: "+progress);
                rotateAngle = 360 * progress;
                Log.d(TAG, "onAnimationUpdate: "+rotateAngle);
                invalidate();
            }
        });
        valueAnimator.start();

其实还有一种更简单的方法去实现,直接旋转画布,就不用去使用三角函数去动态计算了

完整代码如下:

public class RotateProgress extends View {

    private static final String TAG = "RotateProgress";
    //外圈
    Paint outCircle;
    //内圆
    Paint inCircular;

    float strokeWidth = UtilView.sp2px(18);

    //旋转角度
    float rotateAngle = 90;
    //旋转内圆圈的半径
    float inCircularR = UtilView.dip2px(18);

    ValueAnimator valueAnimator = null;

    public RotateProgress(Context context) {
        this(context,null);
    }

    public RotateProgress(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public RotateProgress(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        outCircle = initPaint();
        outCircle.setStyle(Paint.Style.STROKE);
        outCircle.setStrokeWidth(strokeWidth);
        inCircular = initPaint();
        inCircular.setStyle(Paint.Style.FILL);
    }

    private Paint initPaint() {
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        return paint;
    }

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

        float circle = getWidth()/2;

        //绘制外圈
        float left = 0 + strokeWidth/2;
        float top = 0+strokeWidth/2;
        float right = getWidth() - strokeWidth/2;
        float bottom = getHeight() - strokeWidth/2;

        canvas.drawArc( left,  top,  right,  bottom, 0,
        360,false,outCircle);


        float x = (float) (Math.sin(rotateAngle) * (circle - strokeWidth/2 - inCircularR-30) );

        float y = (float) (Math.cos(rotateAngle)*(circle - strokeWidth/2- inCircularR-30));
        //绘制内置圆圈
        canvas.drawCircle(circle+x,circle+y,inCircularR,inCircular);

        Log.d(TAG, "onDraw: x"+x+" y"+y);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        setMeasuredDimension(Math.min(width,height),Math.min(width,height));
    }

    public void startLoading(){
        valueAnimator = ValueAnimator.ofFloat(1);
        valueAnimator.setDuration(100000);
        valueAnimator.setRepeatCount(-1);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float progress = (float) animation.getAnimatedValue();
                Log.d(TAG, "onAnimationUpdate: "+progress);
                rotateAngle = 360 * progress;
                Log.d(TAG, "onAnimationUpdate: "+rotateAngle);
                invalidate();
            }
        });
        valueAnimator.start();
    }

    public void stopAnimator(){
        if(valueAnimator != null){
            valueAnimator.cancel();
            valueAnimator = null;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值