Property Animationを使って画像を回転させながら移動していく途中で、停止・再開させるには AnimatorPauseListener を使うことで可能です。更に AnimatorListenerAdapter を設定しておくと便利です。
API 29
Property Animation
Property Animationの基本的な使い方からの続きです。Property AnimationはAnimationの中間値を実際に作っているので、そのあるタイミングで停止させることも可能です。これはAnimationを見せているだけのView Animationではできないことです。
AnimatorPauseListener
AnimatorListenerを実装してリスナーをObjectに設定すると、開始、キャンセル、終了、リピートがコールバックされますが、一時停止とその後の再開はAnimatorPauseListenerを使わないとできません。
設定はAnimatorListenerとほとんど同様ですが、pauseとresumeにはその時の状態を確認してpause()とresume()を実行させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
public class MainActivity extends AppCompatActivity implements Animator.AnimatorPauseListener{ ObjectAnimator objectAnimator; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... // 一時停止 Button buttonPause = findViewById(R.id.button_pause); buttonPause.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (objectAnimator != null) { if (objectAnimator.isRunning()) { objectAnimator.pause(); } } } }); // 再開 Button buttonResumed = findViewById(R.id.button_resumed); buttonResumed.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (objectAnimator != null) { if (objectAnimator.isPaused()) { objectAnimator.resume(); } } } }); ... objectAnimator.addPauseListener(this); ... } // アニメーション中断 @Override public void onAnimationPause(Animator animation) { Log.d("debug","onAnimationPause()"); } // アニメーション中断からの再開 @Override public void onAnimationResume(Animator animation) { Log.d("debug","onAnimationResume()"); } } |
AnimatorListenerAdapter
AnimatorPauseListenerを実装するだけでは、開始や終了のコールバックを受け取れないので、2つのInterfaceを追加実装することも可能です。ただ、AnimatorListenerAdapterを使うと簡単に処理することができます。
AnimatorListenerAdapterはデフォルトでAnimatorListenerAdapterとAnimatorPauseListenerそれぞれ空のメソッドを実装してくれます。あとはどれか必要なコールバックの処理を記述するだけで済みます。
また、addListener と addPauseListener のどちらでも設定でき機能します。
サンプルコード
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
package your.package.name; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.animation.Animator; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.animation.AnimatorListenerAdapter; public class MainActivity extends AppCompatActivity { private ImageView imageView; private ObjectAnimator objectAnimator; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button buttonStart = findViewById(R.id.button_start); imageView = findViewById(R.id.image_view); imageView.setImageResource(R.drawable.bag); // Animation 開始 buttonStart.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { setAnimetion(); } }); // 一時停止 Button buttonPause = findViewById(R.id.button_pause); buttonPause.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (objectAnimator != null) { if (objectAnimator.isRunning()) { objectAnimator.pause(); } } } }); // 再開 Button buttonResumed = findViewById(R.id.button_resumed); buttonResumed.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (objectAnimator != null) { if (objectAnimator.isPaused()) { objectAnimator.resume(); } } } }); } private void setAnimetion() { // PropertyValuesHolderを使ってX軸方向移動範囲のpropertyを保持 PropertyValuesHolder vhX = PropertyValuesHolder.ofFloat( "translationX", 0.0f, 600.0f); // PropertyValuesHolderを使ってY軸方向移動範囲のpropertyを保持 PropertyValuesHolder vhY = PropertyValuesHolder.ofFloat( "translationY", 0.0f, 1200.0f); // PropertyValuesHolderを使って回転範囲のpropertyを保持 PropertyValuesHolder vhRotaion = PropertyValuesHolder.ofFloat( "rotation", 0.0f, 360.0f); // ObjectAnimatorにセットする objectAnimator = ObjectAnimator.ofPropertyValuesHolder( imageView, vhX, vhY, vhRotaion); // 再生時間を設定 3000msec=3sec objectAnimator.setDuration(3000); //objectAnimator.addListener(new AnimatorListenerAdapter() { objectAnimator.addPauseListener(new AnimatorListenerAdapter() { /* // アニメーション開始で呼ばれる @Override public void onAnimationStart(Animator animation) { Log.d("debug","onAnimationStart()"); } // アニメーションがキャンセルされると呼ばれる @Override public void onAnimationCancel(Animator animation) { Log.d("debug","onAnimationCancel()"); } // アニメーション終了時 @Override public void onAnimationEnd(Animator animation) { Log.d("debug","onAnimationEnd()"); } // 繰り返しでコールバックされる @Override public void onAnimationRepeat(Animator animation) { Log.d("debug","onAnimationRepeat()"); } */ // アニメーション中断 @Override public void onAnimationPause(Animator animation) { Log.d("debug", "onAnimationPause()"); } // アニメーション中断からの再開 @Override public void onAnimationResume(Animator animation) { Log.d("debug", "onAnimationResume()"); } }); // アニメーションを開始する objectAnimator.start(); } } |
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#db9" tools:context=".MainActivity"> <ImageView android:id="@+id/image_view" android:contentDescription="@string/description" android:layout_width="200dp" android:layout_height="200dp" /> <Button android:id="@+id/button_start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" android:text="@string/start" /> <Button android:id="@+id/button_pause" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" android:text="@string/pause" /> <Button android:id="@+id/button_resumed" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" android:text="@string/resume"/> </LinearLayout> |
リソース
strings.xml
1 2 3 4 5 6 7 |
<resources> <string name="app_name">YourAppName</string> <string name="description">bag</string> <string name="start">Start</string> <string name="pause">Pause</string> <string name="resume">Resume</string> </resources> |
サンプル動画
関連ページ:
- android.view.animation
- Property Animation 画像が回転して落ちていくアニメーション
- AnimatorListenerAdapter によるAnimationの一時停止と再開くアニメーション
- frame-by-frame Animation でパラパラアニメーション
- TransitionDrawable クロスフェード animation
Reference:
Property Animation | Android Developers
AnimatorListenerAdapter | Android Developers