java - 你如何在java中为绘制的圆制作动画

标签 java android animation canvas android-animation

我正在制作一个在屏幕上显示多个随机圆圈的应用程序。我想知道我是否可以在显示圆圈然后消失时扩大半径。 所以下面的代码工作只有一个主要问题。在给定的一秒钟内绘制了 100 个圆圈。如果我删除 cool.postDelayed 它只绘制一次。

public class SplashLaunch extends View{
    Handler cool = new Handler();
    DrawingView v;
    Paint newPaint = new Paint();
    int randomWidthOne = 0;
    int randomHeightOne = 0;
    private static int radiusOne = 300;
    final int redColorOne = Color.RED;
    final int greenColorOne = Color.GREEN;
    private static int lastColorOne;
    ObjectAnimator radiusAnimator;
    private final Random theRandom = new Random();
    public SplashLaunch(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }

    private final Runnable circleUpdater = new Runnable() {
        @Override 
        public void run() {
            lastColorOne = theRandom.nextInt(2) == 1 ? redColorOne : greenColorOne;
            newPaint.setColor(lastColorOne);           
            startAnimation(500);
            cool.postDelayed(this, 1000);
            invalidate();
        }
    };

    @Override
    protected void onAttachedToWindow(){
        super.onAttachedToWindow();
        cool.post(circleUpdater);
    }
    protected void onDetachedFromWindow(){
        super.onDetachedFromWindow();
        cool.removeCallbacks(circleUpdater);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);

        if(theRandom == null){
            randomWidthOne =(int) (theRandom.nextInt(Math.abs(getWidth()-radiusOne/2)) + radiusOne/2f);
            randomHeightOne = (theRandom.nextInt((int)Math.abs((getHeight()-radiusOne/2 + radiusOne/2f))));
        }else {
            randomWidthOne =(int) (theRandom.nextInt(Math.abs(getWidth()-radiusOne/2)) + radiusOne/2f);
            randomHeightOne = (theRandom.nextInt((int)Math.abs((getHeight()-radiusOne/2 + radiusOne/2f))));
        }
        canvas.drawCircle(randomWidthOne, randomHeightOne, radiusOne, newPaint);
    }



    public void setRadius(float value){
        this.radiusOne = (int) value;
        invalidate();
    }


    public void startAnimation(int animationDuration) {

        if (radiusAnimator == null || !radiusAnimator.isRunning()) {

            // Define what value the radius is supposed to have at specific time values
            Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
            Keyframe kf2 = Keyframe.ofFloat(0.5f, 180f);
            Keyframe kf1 = Keyframe.ofFloat(1f, 360f);

            // If you pass in the radius, it will be calling setRadius method, so make sure you have it!!!!!
            PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("radius", kf0, kf1, kf2);
            radiusAnimator = ObjectAnimator.ofPropertyValuesHolder(this, pvhRotation);
            radiusAnimator.setInterpolator(new LinearInterpolator());
            radiusAnimator.setDuration(animationDuration);
            radiusAnimator.start();
        }
        else {
            Log.d("Circle", "I am already running!");
        }
    }

    public void stopAnimation() {
        if (radiusAnimator != null) {
            radiusAnimator.cancel();
            radiusAnimator = null;
        }
    }

    public boolean getAnimationRunning() {
        return radiusAnimator != null && radiusAnimator.isRunning();
    }

}

最佳答案

你需要有两件事。一个自定义 View (我知道你有那个)和一个 ObjectAnimator。它基于 Java 反射,只要您知道如何正确绘制它,就不会在意您正在制作什么动画。

public class CustomCircleView extends View {

    private ObjectAnimator radiusAnimator;
    private float radius;

    public CustomCircleView(Context context) {
        super(context);
    }

    public CustomCircleView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomCircleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public void setRadius(float value){
        this.radius = value;
        invalidate();
    }


    public void startAnimation(int animationDuration) {

        if (radiusAnimator == null || !radiusAnimator.isRunning()) {

            // Define what value the radius is supposed to have at specific time values
            Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
            Keyframe kf2 = Keyframe.ofFloat(0.5f, 180f);
            Keyframe kf1 = Keyframe.ofFloat(1f, 360f);

            // If you pass in the radius, it will be calling setRadius method, so make sure you have it!!!!!
            PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("radius", kf0, kf1, kf2);
            radiusAnimator = ObjectAnimator.ofPropertyValuesHolder(this, pvhRotation);
            radiusAnimator.setInterpolator(new LinearInterpolator());
            radiusAnimator.setDuration(animationDuration);
            radiusAnimator.start();
        }
        else {
            Log.d("Circle", "I am already running!");
        }
    }

    public void stopAnimation() {
        if (radiusAnimator != null) {
            radiusAnimator.cancel();
            radiusAnimator = null;
        }
    }

    public boolean getAnimationRunning() {
        return radiusAnimator != null && radiusAnimator.isRunning();
    }


    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        canvas.drawCircle(x, y, radius, circlePaint);
    }
}

关于java - 你如何在java中为绘制的圆制作动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29883704/

相关文章:

java - 生成安全动态 key 的最佳方法

java - 包含上下文的 AWS 开发工具包引用 - Android

java - 为垃圾收集清除 BST 的最佳方法是什么?

java - JBoss 多个 SLF4J 绑定(bind)错误

performance - 如何以最佳效率在paperjs中重新定位路径线?

javascript - 在完成 javascript css 后重复动画

java - Android:如何找到屏幕的宽度和高度?

android - 计算圆弧中心点,知道它的开始和结束度数

android - 通过intent时提取surfaceView、surfaceHolder

java - 在动画期间更改 Z 顺序