業務で少し調べたことのメモ程度に。
AndroidでViewをアニメーションさせたいときの実装方法の一つとして、Transitionがあります。
Transition
Transitionの概要については、公式ドキュメント、もしくはyarakiさんによる下記のスライドが参考になります。
yaraki.github.io
Transitionは、アニメーションの前後のViewの状態を保存、比較をして、それに応じたAnimatorを生成し実行してくれる便利なAPIです。
例えば下記のようなコードを実行すると、binding.target Viewの表示・非表示がフェードしながら切り替わります。
TransitionManager.beginDelayedTransition(binding.root)
binding.target.isVisible = !binding.target.isVisible
beginDelayedTransition関数は魔法のような関数となっており、これを実行後にViewの表示切り替えを行うことで、よしなにアニメーションをしてくれます。
上記の例では、内部でデフォルトとして設定されているTransitionクラスを利用して動きのアニメーションを実現します。もちろんデフォルト以外の動きを実現するために、自分で独自のTransitionクラスを定義し渡すこともできます。
val myTransition = MyTransition()
TransitionManager.beginDelayedTransition(binding.root, myTransition)
Listenerを追加する
よくあるパターンとして、アニメーションの終了後に何らかの処理を実行したい場合があります。
Transitionが終了したタイミングでよしなに処理を行いたい場合には、TransitionクラスのaddListener関数を使って、Listenerを追加します。
以下はTransitionクラスのaddListener関数の内部実装です。
Adds a listener to the set of listeners that are sent events through the
life of an animation, such as start, repeat, and end.
@param listener
@return
@NonNull
public Transition addListener(@NonNull TransitionListener listener) {
if (mListeners == null) {
mListeners = new ArrayList<>();
}
mListeners.add(listener);
return this;
}
カスタムTransitionを定義している場合はTransition初期化時にaddListener関数を呼び出すことで問題なくListenerを追加できます。
val myTransition = MyTransition().addListener(object : Transition.TransitionListener() {
...
})
TransitionManager.beginDelayedTransition(binding.root, myTransition)
では、カスタムTransitionを定義していない場合(=beginDelayedTransition関数の引数にTransitionクラスを渡さない場合)はどうすればいいのでしょうか?
そのような場合には、Transitionクラスが内部で保持している、デフォルトのTransitionクラスを初期化し、このクラスにListenerを追加できます。
デフォルトのTransitionクラスというのは、AutoTransitionというクラスです。内部実装を読むと、TransitionManagerクラスに、private staticフィールドとして定義されていることがわかります。
public class TransitionManager {
...
private static Transition sDefaultTransition = new AutoTransition();
なのでこのAutoTransitionクラスを初期化して利用をすれば、問題ないです。
val transition = AutoTransition().addListener(...)
TransitionManager.beginDelayedTransition(binding.root, transition)
Tips
addListener関数には素直にTransitionListenerクラス自体を渡すこともできますが、代わりにこのListenerクラスを実装したTransitionListenerAdapterというクラスを渡すこともできます。AdapterクラスはAndroidのAPIにあるinterfaceクラスをただoverrideしただけ(独自の処理はない)のclassです。TransitionListener以外のListenerなどに対しても定義されていることがあります。
Adapterクラスがintefaceに定義されている関数をすべて空で実装しているため、このAdapterクラスを代わりに利用することで、Listenerに定義されている関数の中で、開発者がoverrideしたい関数のみをAdapterクラスを介してoverrideして利用することができます。
最終的には以下のようなコードとなりました。
val transition = AutoTransition()
.addListener(object : TransitionListenerAdapter() {
override fun onTransitionEnd(transition: Transition) {
}
})
TransitionManager.beginDelayedTransition(binding.root, transition)
binding.target.isVisible = !binding.target.isVisible
まとめ
- AndroidでViewのアニメーションを行う際にはTransition APIも選択肢の一つ
- Transition APIを使ったアニメーションで、所定のタイミングで処理を実行したい場合にはTransitionクラスのaddListener関数を利用する
- デフォルトで用意されているTransitionクラスはAutoTransition
- TransitionListener interfaceにはTransitionListenerAdapterクラスが用意されている