Android Анимированный вид кривой Sin Wave - PullRequest
0 голосов
/ 18 июня 2020

Попытка создать настраиваемый вид, который будет генерировать синусоидальную волну по всей длине вида. Его можно будет использовать повторно. У меня проблема с разделением чертежа сегмента в методе onDraw (). В настоящее время они рисуются одновременно, и я хотел бы анимировать слева направо. Я считаю, что проблема в том, что затраченное время / время запуска просто недостаточно точны, просто запуск анимации имеет слишком большое отставание. В настоящее время только dr aws последний сегмент, который поддерживает эту теорию. Есть лучший способ сделать это?

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);

1 Ответ

0 голосов
/ 18 июня 2020

После того, как я еще пару часов оттолкнулся головой о стену, пытаясь понять это, я нашел достойное решение. По-прежнему нужно настроить под любой размер экрана, но анимация работает и довольно плавная.

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);
    }
}
...