关于Android椭圆动画实现,非ValueAnimation方式
最近由于项目需要,实现了一个自定义椭圆动画view
OvalView
import androidx.annotation.Nullable;
public class OvalView extends View {
private int width;
private int height;
private int ovalWidth = 440;
private int ovalHeight = 230;
public RectF oval2 = new RectF(20, 100, ovalWidth, 100 + ovalHeight);
public OvalView(Context context) {
super(context);
}
public OvalView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public OvalView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = widthMeasureSpec;
height = heightMeasureSpec;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/*
* 方法 说明 drawRect 绘制矩形 drawCircle 绘制圆形 drawOval 绘制椭圆 drawPath 绘制任意多边形
* drawLine 绘制直线 drawPoin 绘制点
*/
// 创建画笔
Paint p = new Paint();
p.setColor(Color.RED);// 设置红色
p.setStyle(Paint.Style.STROKE);
/* 设置渐变色 这个正方形的颜色是改变的 */
Shader mShader = new LinearGradient(0, 0, 100, 100,
new int[]{Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW,
Color.LTGRAY}, null, Shader.TileMode.REPEAT); // 一个材质,打造出一个线性梯度沿著一条线。
p.setShader(mShader);
// p.setColor(Color.BLUE);
canvas.drawArc(oval2, 180, 60, true, p);
// 画弧,第一个参数是RectF:该类是第二个参数是角度的开始,第三个参数是多少度,第四个参数是真的时候画扇形,是假的时候画弧线
canvas.drawOval(oval2, p);
float[] mCurrentPosition = updatePosition1();
if (mCurrentPosition[0] == 0 && mCurrentPosition[1] == 0) {
canvas.drawCircle(20, 100 + (ovalHeight / 2), 20, p);
//startAn1(180f, 100f, false);
} else {
canvas.drawCircle(mCurrentPosition[0], mCurrentPosition[1], 20, p);
}
float[] mCurrentPosition1 = updatePosition2();
if (mCurrentPosition1[0] == 0 && mCurrentPosition1[1] == 0) {
canvas.drawCircle(ovalWidth, 100 + (ovalHeight / 2), 20, p);
} else {
canvas.drawCircle(mCurrentPosition1[0], mCurrentPosition1[1], 20, p);
}
}
private float[] updatePosition1() {
float[] mCurrentPosition = new float[2];
float cx = 20 + ovalWidth / 2;
float cy = 100 + (ovalHeight / 2);
if (countSweepAngle == 0) {
return mCurrentPosition;
}
Path path = new Path();
// path.addOval(oval2, Path.Direction.CW);
path.addArc(oval2, startAngle, sweepAngle);
//pathMeasure用来计算显示坐标
PathMeasure pathMeasure = new PathMeasure(path, true);
//float value = 90 * 2.9f;
pathMeasure.getPosTan(pathMeasure.getLength() / 2, mCurrentPosition, null);
Log.e("tuoyuan", mCurrentPosition[0] + " " + mCurrentPosition[1]);
return mCurrentPosition;
}
private float[] updatePosition2() {
float[] mCurrentPosition = new float[2];
float cx = 20 + ovalWidth / 2;
float cy = 100 + (ovalHeight / 2);
if (countSweepAngle1 == 0) {
return mCurrentPosition;
}
Path path = new Path();
// path.addOval(oval2, Path.Direction.CW);
path.addArc(oval2, startAngle1, sweepAngle);
//pathMeasure用来计算显示坐标
PathMeasure pathMeasure = new PathMeasure(path, true);
//float value = 90 * 2.9f;
pathMeasure.getPosTan(pathMeasure.getLength() / 2, mCurrentPosition, null);
Log.e("tuoyuan", mCurrentPosition[0] + " " + mCurrentPosition[1]);
return mCurrentPosition;
}
private final float sweepAngle = 10f;
private float startAngle = 180f;
private float countSweepAngle = 0f;
public void startAn1() {
new Thread(new Runnable() {
@Override
public void run() {
try {
while (true) {
startAnimation1();
startAnimation2();
Thread.sleep(300);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
public void startAnimation1() {
if (startAngle == 360f) {
startAngle = 0f;
countSweepAngle = 0f;
} else if (startAngle == 180f && countSweepAngle == 180f) {
startAngle = 180f;
countSweepAngle = 0f;
} else {
startAngle += sweepAngle;
}
countSweepAngle += 10f;
postInvalidate();
}
private float startAngle1 = 0f;
private float countSweepAngle1 = 0f;
public void startAnimation2() {
if (startAngle1 == 360f && countSweepAngle1 == 180f) {
startAngle1 = 0f;
countSweepAngle1 = 0f;
} else if (startAngle == 180f && countSweepAngle1 == 180f) {
startAngle1 = 180f;
countSweepAngle1 = 0f;
} else {
startAngle1 += sweepAngle;
}
countSweepAngle1 += 10f;
postInvalidate();
}
}
后续源码会附上
|