LoginSignup
11
14

More than 5 years have passed since last update.

[Android] ステートマシンでアニメーションの順次実行を制御する

Posted at

あるViewに対してアニメーション①を実行し、終了したらアニメーション②を実行し、、ということを実現したいとします。ただリスナーでアニメーションの終了を検知しているとコードがネストしたり、繰り返したい場合にどうすればいいか困ったりします。

そういう場合は、enum でステートマシンを作ってアニメーションを実行するとコードがすっきりします。

例えば下記のコードは、あるViewに対してアニメーション AnimState1 AnimState2 AnimState3 の順次実行を繰り返し行うコードの例です。

SomeAnimState.java
enum SomeAnimState {
    Stop {
        @Override
        protected void start(View view) {
            changeState(view, AnimState1);
        }
    },
    AnimState1 {
        @Override
        protected void enter(View view) {
            view.setAlpha(0);
            view.animate().alpha(1.0F).setDuration(1000).setInterpolator(new LinearInterpolator()).setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    changeState(view, AnimState2);
                }
            });
        }
    },
    AnimState2 {
        @Override
        protected void enter(View view) {
            view.animate().scaleX(2.0F).scaleY(2.0F).setDuration(1000).setInterpolator(new OvershootInterpolator()).setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    changeState(view, AnimState3);
                }
            });
        }
    },
    AnimState3 {
        @Override
        protected void enter(View view) {
            view.animate().scaleX(1.0F).scaleY(1.0F).setDuration(1500).setInterpolator(new FastOutSlowInInterpolator()).setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    changeState(view, AnimState1);
                }
            });
        }
    },
    ;

    private static SomeAnimState currentState = Stop;

    public static void startAnim(View view) {
        currentState.start(view);
    }

    public static void stopAnim(View view) {
        currentState.stop(view);
    }

    protected void start(View view) {}

    @CallSuper
    protected void stop(View view) {
        currentState.changeState(view, Stop);
    }

    protected void enter(View view) {} // 各ステートが開始した際にさせる処理をオーバーライドで記述

    protected void exit(View view) {} // 各ステートが終了する際にさせる処理をオーバーライドで記述

    protected void changeState(View view, SomeAnimState nextState) {
        if (currentState != this) return;
        currentState.exit(view);
        currentState = nextState;
        currentState.enter(view);
    }
}

アニメーションを開始する場合は、staticメソッド startAnim() を呼び出します。すると各ステートの start() を呼び出すようになっているので、もし Stop ステータスでない場合は、何もしないようになっています。

アニメーションの開始
SomeAnimState.startAnim(someView);

同様に、繰り返しアニメーションにしている場合等でアニメーションを終了する場合は、staticメソッド stopAnim() を呼び出します。

アニメーションの終了
SomeAnimState.stopAnim(someView);

繰り返しにしている/していないに関わらず、アニメーション実行中にActivityの終了等でViewが死ぬケースがあるので、onDestroy() できちんと終了を呼び出しておくと安全です。

以上

11
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
14