一、首先介绍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是一个进度最前面的小星星,可以替换为其它图片
效果图:
网友评论