[Android高级动画] 如何让箭头按圆形旋转?

用Android动画,如何让一个箭头按圆形旋转?

arrow like this:

arrow.png

最终效果图:

效果图
一、分析
1、两个关键值

箭头按圆形旋转,需要两个关键值,一个是圆形坐标,一个是对应圆形坐标位置的角度。

圆形坐标:用来实现箭头移动
坐标点的角度:用来改变箭头的方向

2、两个关键API

a、实现箭头移动和旋转可以使用:
Matrix 类 postTranslate和postRotate方法。
b、获取圆坐标,和对应的角度,可以使用:
PathMeasure类的getPosTan方法。

二、具体实现
1、先在屏幕重要画个圆:
//画布移到屏幕中心
canvas.translate((float) mWidth / 2, (float) mHeight / 2);
//画一个圆
mPath.addCircle(0, 0, 200, Path.Direction.CW);
canvas.drawPath(mPath, mPaint);

画之前需要先获取屏幕宽高(重写View的onSizeChanged):

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = w;
        mHeight = h;
    }
2、获取圆形的某个位置坐标,和对应位置的角度。
PathMeasure pathMeasure = new PathMeasure(mPath,false);
 //圆周长
float distance = pathMeasure.getLength();
//将distance段的实际坐标值和单位圆坐标值分别保持到pos、tan中
pathMeasure.getPosTan(distance,pos,tan);
float px = pos[0];//实际x坐标值
float py = pos[1];//实际y坐标值 
//根据单位圆坐标值,计算出当前位置的角度值
float degrees = (float) (Math.atan2(tan[1],tan[0]) * 180/Math.PI); 
3、绘制箭头
//获取图片宽高度
int width = mBitmap.getWidth();
int height = mBitmap.getHeight();
//设置箭头旋转角度
mMatrix.postRotate(degrees,(float) width/2,(float) height/2);
//设置箭头位置
mMatrix.postTranslate(px - (float) width/2,py- (float)height/2);
//绘制
canvas.drawBitmap(mBitmap,mMatrix,mPaint);

以上我们就可以将箭头显示在圆环上了,但是它还不能动起来,还只是静态的。

怎么让它转起来呢?

4、如何让箭头转起来呢?

我们需要不停的改变箭头的位置,和角度。
先定义一个成员变量:

 private float mFloat = 0;

让mFloat 在0到1之间变化,然后再重新获取pos、和tan值:

mFloat += 0.01;
if(mFloat >= 1){
   mFloat = 0;
}
pathMeasure.getPosTan(distance * mFloat,pos,tan);

然后再不停到重新绘制:

invalidate();

这样就可以让箭头转起来了。

最后附上完整代码:

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;

/**
 * 图片圆型旋转动画
 */
public class CircleAnimatorView extends View {
    public CircleAnimatorView(Context context) {
        this(context, null);
    }

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

    public CircleAnimatorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = w;
        mHeight = h;
    }

    private Paint mPaint = new Paint();
    private Path mPath = new Path();
    private int mWidth;
    private int mHeight;
    private Bitmap mBitmap;


    //保持圆上xy的实际坐标
    private float[] pos = new float[2];
    //保持单位圆上xy的坐标
    private float[] tan = new float[2];
    
    private Matrix mMatrix = new Matrix();

    private float mFloat = 0;

    private void init() {
        mPaint.setColor(Color.BLACK);
        mPaint.setStrokeWidth(4);
        mPaint.setStyle(Paint.Style.STROKE);

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 4;//缩小4倍
        mBitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.arrow,options);

    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画布移到屏幕中心
        canvas.translate((float) mWidth / 2, (float) mHeight / 2);

        mPath.reset();
        //添加一个圆
        mPath.addCircle(0, 0, 200, Path.Direction.CW);
        canvas.drawPath(mPath, mPaint);
        PathMeasure pathMeasure = new PathMeasure(mPath,false);

        //圆周长
        float distance = pathMeasure.getLength(); 

        mFloat += 0.01;

        if(mFloat >= 1){
            mFloat = 0;
        }

        pathMeasure.getPosTan(distance * mFloat,pos,tan);


        float px = pos[0];
        float py = pos[1];
 

        float degrees = (float) (Math.atan2(tan[1],tan[0]) * 180/Math.PI);
        Log.d("View-->","onDraw | degrees:"+degrees);

        int width = mBitmap.getWidth();
        int height = mBitmap.getHeight(); 

        mMatrix.reset();


        //必须选postRotate,再调用 postTranslate
        mMatrix.postRotate(degrees,(float) width/2,(float) height/2);
        mMatrix.postTranslate(px - (float) width/2,py- (float)height/2);


        canvas.drawBitmap(mBitmap,mMatrix,mPaint);

        invalidate();

    }
}

你可能感兴趣的:([Android高级动画] 如何让箭头按圆形旋转?)