[尝试创建自定义视图,将在视图的长度范围内产生一个正弦波。这应该可以重用。我在onDraw()方法中分割线段图时遇到问题。目前,它们是同时绘制的,我想从左到右进行动画处理。我认为问题在于经过时间/开始时间不够准确,动画开始的时间太滞后。目前仅得出支持该理论的最后一段。有一个更好的方法吗?
CurveView
public class CurveView extends View {
private Paint paint = new Paint();
private long startTime;
private double animationSegmentLength;
private RectF rectF1;
private RectF rectF2;
private RectF rectF3;
private RectF rectF4;
private RectF rectF5;
private RectF rectF6;
private float arcAngle = 0;
public CurveView(Context context) {
super(context);
init(null, 0);
}
public CurveView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(attrs, 0);
}
public CurveView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs, 0);
}
private void init(AttributeSet attrs, int defStyle){
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
paint.setStrokeWidth(6);
}
public float getArcAngle() {
return arcAngle;
}
public void setArcAngle(float arcAngle) {
this.arcAngle = arcAngle;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int startEndY = getHeight() / 2;
long elapsedTime = System.currentTimeMillis() - startTime;
canvas.drawLine(0, startEndY, getWidth(), startEndY, paint);
if(elapsedTime < animationSegmentLength) {
canvas.drawArc(rectF1, 180, -arcAngle, false, paint);
}else if(elapsedTime < 2 * animationSegmentLength) {
canvas.drawArc(rectF2, 180, arcAngle, false, paint);
}else if(elapsedTime < 3 * animationSegmentLength) {
canvas.drawArc(rectF3, 180, -arcAngle, false, paint);
}else if(elapsedTime < 4 * animationSegmentLength) {
canvas.drawArc(rectF4, 180, arcAngle, false, paint);
}else if(elapsedTime < 5 * animationSegmentLength) {
canvas.drawArc(rectF5, 180, -arcAngle, false, paint);
}else{
canvas.drawArc(rectF6, 180, arcAngle, false, paint);
}
}
@Override
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld){
super.onSizeChanged(xNew, yNew, xOld, yOld);
int topSpacing = yNew / 10;
int bottomSpacing = yNew - (yNew / 10);
float f1Right = xNew / 6f;
float f2Right = (2f * xNew) / 6;
float f3Right = (3f * xNew) / 6;
float f4Right = (4f * xNew) / 6;
float f5Right = (5f * xNew) / 6;
rectF1 = new RectF(0, topSpacing, f1Right, bottomSpacing);
rectF2 = new RectF(f1Right, topSpacing, f2Right, bottomSpacing);
rectF3 = new RectF(f2Right, topSpacing, f3Right, bottomSpacing);
rectF4 = new RectF(f3Right, topSpacing, f4Right, bottomSpacing);;
rectF5 = new RectF(f4Right, topSpacing, f5Right, bottomSpacing);
rectF6 = new RectF(f5Right, topSpacing, xNew, bottomSpacing);
}
public void setDuration(long durationMillis) {
animationSegmentLength = (double) durationMillis / 6;
}
@Override
public void startAnimation(Animation animation) {
super.startAnimation(animation);
startTime = System.currentTimeMillis();
}
}
CurveAnimation
public class CurveAnimation extends Animation {
private CurveView curveView;
private float oldAngle;
private float newAngle;
public CurveAnimation(CurveView curveView, int newAngle) {
this.oldAngle = curveView.getArcAngle();
this.newAngle = newAngle;
this.curveView = curveView;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation transformation) {
float angle = 0 + ((newAngle - oldAngle) * interpolatedTime);
curveView.setArcAngle(angle);
curveView.requestLayout();
}
@Override
public void setDuration(long durationMillis) {
super.setDuration(durationMillis);
curveView.setDuration(durationMillis);
}
}
初始化
CurveAnimation animation = new CurveAnimation(curveView, 180);
animation.setDuration(1500);
curveView.startAnimation(animation);
在将头从墙上扑过去两个多小时后,我想出了一个不错的解决方案。仍然需要进行调整以适合任何屏幕尺寸,但是动画有效并且相当流畅。
public class CurveView extends View {
private Paint paint = new Paint();
private int centerHeight;
private int valueAnimation;
public CurveView(Context context) {
super(context);
init(null, 0);
}
public CurveView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(attrs, 0);
}
public CurveView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs, 0);
}
private void init(AttributeSet attrs, int defStyle){
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
paint.setStrokeWidth(6);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawLine(0, getHeight()/ 2f, getWidth(), getHeight()/2f, paint);
for (int i = 0; i < getWidth() - valueAnimation; i = i + 10) {
int startX = i;
int startY = (int) (centerHeight + 100*(float)Math.sin(i/180.0*Math.PI));
int endX = i + 10;
int endY = (int) (centerHeight + 100*(float)Math.sin ((i + 10)/180.0*Math.PI));
canvas.drawLine(startX, startY, endX, endY, paint);
}
}
@Override
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld){
super.onSizeChanged(xNew, yNew, xOld, yOld);
centerHeight = getHeight() / 2;
ValueAnimator valueAnimatorLoading = ValueAnimator.ofInt(getWidth(), 0);
valueAnimatorLoading.addUpdateListener(valueAnimator -> {
valueAnimation = (int) (Integer) valueAnimator.getAnimatedValue();
invalidate();
});
valueAnimatorLoading.addListener(new AnimatorListenerAdapter()
{
@Override
public void onAnimationEnd(Animator animation)
{
System.out.println("On Finish");
}
});
valueAnimatorLoading.start();
valueAnimatorLoading.setDuration(3000);
}
}