美文网首页
[Android高级动画] 如何让箭头按圆形旋转?

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

作者: 小米Metre | 来源:发表于2019-06-09 17:04 被阅读0次

    用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高级动画] 如何让箭头按圆形旋转?

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