美文网首页
Android自定义带动画圆弧简单demo

Android自定义带动画圆弧简单demo

作者: 枫从流年 | 来源:发表于2017-11-02 15:30 被阅读0次

一、首先介绍Math.sin和Math.cos方法,即数学里面正弦,余弦取值:
Math.sin和Math.cos方法传值不是我们常说的角度,而是弧度,弧度计算公式为:角度2Math.PI/360,即:角度*Math.PI/180,如30度角的正弦值为:Math.sin(30 * Math.PI / 180)。

二、如何获取圆上某点的坐标:
假设圆点坐标(a, b),半径为r,角度为α,则圆上某点坐标(x, y)中,x = a + r * Math.cos(α * Math.PI / 180),y = b + r * Math.sin(α * Math.PI / 180)。

三、具体代码实现如下:
public class TestView extends View {

private Paint paint;
private Paint strokePaint;
private Paint.FontMetrics fontMetrics;
private int size;
private int strokeWidth;
private float targetDegree = 0;
private float newSize;
private float radius;
private ValueAnimator animator;
private Bitmap bitmap;
private RectF rectF;
/**
 * 动画开始角度 顺时针从上往下分别为 270,0,90,180
 */
private static final float ANIMATION_START_DEGREE = 270;
/**
 * 动画结束角度,开始角度+需要运行的角度
 */
private static final float ANIMATION_TARGET_DEGREE = ANIMATION_START_DEGREE + 210;
/**
 * 单位dp
 */
private static final float BORDER_WIDTH = 5;

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

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

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

private void init(){
    paint = new Paint();
    paint.setColor(Color.parseColor("#b1ff56"));
    strokeWidth = DisplayUtil.dip2px(BORDER_WIDTH, getContext());
    paint.setStrokeWidth(strokeWidth);
    paint.setStyle(Paint.Style.STROKE);
    paint.setAntiAlias(true);
    /** 结合处为圆弧*/
    paint.setStrokeJoin(Paint.Join.ROUND);
    /** 设置画笔的样式 Paint.Cap.Round ,Cap.SQUARE等分别为圆形、方形*/
    paint.setStrokeCap(Paint.Cap.ROUND);

    strokePaint = new Paint();
    strokePaint.setColor(Color.parseColor("#0e000000"));
    strokePaint.setStrokeWidth(strokeWidth);
    strokePaint.setStyle(Paint.Style.STROKE);
    strokePaint.setAntiAlias(true);
    /** 结合处为圆弧*/
    strokePaint.setStrokeJoin(Paint.Join.ROUND);
    /** 设置画笔的样式 Paint.Cap.Round ,Cap.SQUARE等分别为圆形、方形*/
    strokePaint.setStrokeCap(Paint.Cap.ROUND);

    fontMetrics = paint.getFontMetrics();
    size = DisplayUtil.dip2px(100, getContext());
    Bitmap tempBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.star_small);
    Matrix matrix = new Matrix();
    newSize = DisplayUtil.dip2px(20, getContext());
    float tempSize = tempBitmap.getWidth();
    float scale = newSize / tempSize;
    matrix.postScale(scale, scale);
    bitmap = Bitmap.createBitmap(tempBitmap, 0, 0, tempBitmap.getWidth(), tempBitmap.getHeight(), matrix, true);
    radius = (size - strokeWidth) / 2;

    rectF = new RectF(strokeWidth / 2, strokeWidth / 2, size - strokeWidth / 2, size - strokeWidth / 2);

    animator = ValueAnimator.ofFloat(ANIMATION_START_DEGREE, ANIMATION_TARGET_DEGREE);
    animator.setDuration(2000);
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            targetDegree = (float) animation.getAnimatedValue();
            invalidate();
        }
    });

    targetDegree = ANIMATION_START_DEGREE;
    invalidate();
}

private int getFontHeight() {
    Paint.FontMetrics fm = paint.getFontMetrics();
    return (int) Math.ceil(fm.descent - fm.top);
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if(targetDegree > 0) {
        canvas.translate(newSize / 2, newSize / 2);
        //画笔宽度中心算边距
        canvas.drawArc(rectF, ANIMATION_START_DEGREE, 360, false, strokePaint);
        canvas.drawArc(rectF, ANIMATION_START_DEGREE, targetDegree - ANIMATION_START_DEGREE, false, paint);
        float x = (float) (size / 2 + radius * Math.cos(targetDegree * Math.PI / 180) - bitmap.getWidth() / 2);
        float y = (float) (size / 2 + radius * Math.sin(targetDegree * Math.PI / 180) - bitmap.getHeight() / 2);
        canvas.drawBitmap(bitmap, x, y, paint);
    }
}

public void startAnimation(){
    if(animator != null) {
        if(animator.isRunning()){
            animator.cancel();
        }
        animator.start();
    }
}

public void setInterpolator(TimeInterpolator value){
    if(animator != null){
        animator.setInterpolator(value);
    }
}

public void recycle(){
    strokePaint = null;
    paint = null;
    if(animator != null){
        if(animator.isRunning()) {
            animator.cancel();
        }
        animator.end();
        animator = null;
    }
    if(bitmap != null){
        bitmap.recycle();
        bitmap = null;
    }
}

}

布局如下:
<RelativeLayout
android:layout_width="120dp"
android:layout_height="120dp">

    <ImageView
        android:layout_width="90dp"
        android:layout_height="90dp"
        android:src="@mipmap/cemara"
        android:layout_centerInParent="true"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="科学\n认知"
        android:textColor="#ffffff"
        android:textSize="14sp"
        android:layout_centerInParent="true"/>

    <com.example.myapplication.view.TestView
        android:id="@+id/testView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"/>

</RelativeLayout>

代码中绘制的bitmap是一个进度最前面的小星星,可以替换为其它图片
效果图:

device-2017-11-02-152842.gif

相关文章

网友评论

      本文标题:Android自定义带动画圆弧简单demo

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