こんにちは
4.4(KitKat)からAndroidに登場し、5.0(Lollipop)で開発を継続したアニメーションの
Transitions APIのトピックは、まだハブで取り上げられていません。 私の記事では、アニメーションを使用してアニメーションを単純化する方法と、
Android 4.0以降を
搭載した任意のデバイスに適用する方法について説明します。

Android 4.4とともに、レイアウトの変更をアニメーション化する新しいメカニズムが導入されました。 バージョン4.0でも、この問題の最初の解決策が表示されました-ViewGroupのanimateLayoutChangeフラグです。 しかし、getLayoutTransition()メソッドを呼び出してそのパラメーターを変更しても、十分な柔軟性がなく、変更のアニメーション化(遷移)を完全に制御することはできませんでした。
KitKat Transition APIは、シーンの概念、
シーン 、および
シーン間のいくつかの変更をもたらします。 それらに加えて、
シーンルートの概念を導入して、シーンの変更が発生するルートレイアウトを決定します。 また、シーン自体はViewGroupに対する一種のラッパーであり、シーンの特定の状態とそれに含まれるすべてのViewオブジェクトを記述します。
次に、
トランジション自体について説明します。 これは、ビューから必要なパラメーター値を読み取るためのメカニズムであり、シーンを変更し、アニメーションを生成するとこれらの状態がスムーズに変更されるときに変更されます。
Transitions APIの最も単純なユースケースから始めましょう。
レイアウトの現在の状態が最初のシーンであると想像してください。 正方形があるとしましょう。
xmlを使用してレイアウトを説明しましょう。
<FrameLayout android:id="@+id/container" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <View android:id="@+id/transition_square" android:layout_width="@dimen/square_size_normal" android:layout_height="@dimen/square_size_normal" android:background="@color/square_bg"/> </FrameLayout>
ここで、正方形のサイズをアニメーション化したいだけです。 シーンの概念に慣れ始めるために、これを2番目のシーンへの移行と呼びます。
ViewGroup sceneRoot = (ViewGroup) findViewById(R.id.container); View square = mSceneRoot.findViewById(R.id.transition_square); int newSquareSize = getResources().getDimensionPixelSize(R.dimen.square_size_expanded);
結果:

悪くない、ただ一行のアニメーション。 また、レイアウト内にはこのような変更がいくつあってもかまいません。
それでは、いくつかのアニメーションパラメータを設定してみましょう。 これを行うには、実行する特定の遷移を指定する必要があります。
beginDelayedTransitionメソッドは、Transitionクラスの子孫の2番目のパラメーターを取ることができます。 今から話をするのは彼らについてです。
単純な遷移タイプ
- ChangeBounds 。 最初の例で処刑されたのは彼だった。 これは遷移であり、レイアウト内のビューの座標とその寸法を変更する役割を果たします。
- フェード よく知られているアニメーションのフェードインとフェードアウトを組み合わせています。 彼は、最初のシーンでビューが表示された瞬間に実行されるトランジションのために考案された可視性クラスの相続人ですが、2番目のシーンに切り替えると消える、または逆に表示されます。
- TransitionSet また、トランジションの後継ですが、順番にまたは同時に実行される他のトランジションの任意の数のコレクションです。 シーケンスは、setOrderingメソッドを使用して設定されます。
- AutoTransition 。 これはそのようなTransitionSetであり、Fade.OUTパラメーターを使用して順次実行されるフェード、Fade.INパラメーターを使用してChangeBoundsおよびFadeのコレクションにすぎません。 したがって、まず、フェードアウトエフェクトでは、2番目のシーンにないすべてのビューが非表示になり、次にこれらのパラメーターが変更されたビューの移動とサイズ変更が行われ、最後に、2番目のシーンの新しい要素がフェードインで表示されます。 最初の例のように、beginDelayedTransitionメソッドに特定の遷移を指定しなかった場合に実行されるのはAutoTransitionです。
シーン
シーンに戻ります。 最初の例では、APIを使用する最も簡単な方法を見ました。 ただし、シーンをより形式的に記述すると、たとえば、シーンを切り替えるのがより便利になります。
アクティビティを変更するためのボタンと、シーンのルートとなるFrameLayoutがあるように、アクティビティのレイアウトを説明します。 その中に、最初のシーンであるレイアウトをすぐに配置しますが、別のファイルに配置します。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <Button android:id="@+id/btn_change_scene" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Change scene" android:layout_gravity="center_horizontal" /> <FrameLayout android:id="@+id/scene_root" android:layout_width="match_parent" android:layout_height="match_parent"> <include layout="@layout/scene1"/> </FrameLayout> </LinearLayout>
scene1のコンテンツ。 そこに同じ正方形を置きますが、左上隅に:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout android:id="@+id/container" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <View android:id="@+id/transition_square" android:layout_width="@dimen/square_size_normal" android:layout_height="@dimen/square_size_normal" android:background="@color/square_bg" android:layout_gravity="top|left"/> </FrameLayout>
そしてscene2ファイルを作成します。 四角形を右上隅に移動し、サイズを大きくします。 また、最初のシーンになかったTextViewを追加します。
<FrameLayout android:id="@+id/container" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <View android:id="@+id/transition_square" android:layout_width="@dimen/square_size_expanded" android:layout_height="@dimen/square_size_expanded" android:background="@color/square_bg" android:layout_gravity="top|right"/> <TextView android:id="@+id/transition_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="This text fades in." android:textAppearance="?android:attr/textAppearanceLarge"/>/> </FrameLayout>
onCreateでは、アクティビティは次のことを説明します。
ViewGroup sceneRoot = (ViewGroup) findViewById(R.id.scene_root);
結果:

そして、主なものについて。 バックポート
このAPIを使用する人が少ない理由と、このAPIを知っている人が少ない理由を簡単に理解できます。 開発者はAndroid 2.xのサポートを拒否する道徳的権利を最近認識したばかりであり、ほとんどの新しいプロジェクトはついにminSdk Android 4.0のサポートから始まります。 しかし、これまでのところ、4.4以降でのみ動作するAPIを使用することはほとんど意味がありません。これは、ほとんどのデバイスがまだ古いバージョンであるためです。
しかし! Transition APIは既にAndroid 4.0以降で使用でき、アニメーションはどこでも同じように機能します。 これを行うために、私は
Transitions Everywhereというライブラリを開発しています。 これは、古いバージョンのAndroidへのTransition APIのバックポートです。 プロジェクトに統合するには、ライブラリをgradle依存関係として接続する必要があります。
dependencies { compile "com.andkulikov:transitionseverywhere:1.7.4" }
また、このAPIに関連付けられているすべてのクラスについて、インポートをパッケージ
com.transitionseverywhereに置き換えます* android.transitionの代わりに
*図書館について
このトピックに興味を持ち始めたとき、2つの類似したライブラリを見つけました。
github.com/guerwan/TransitionsBackportgithub.com/pardom/TransitionSupportLibrary彼らを結びつけているのは、彼らの開発者が明らかに彼らの開発で得点し、彼らの両方がAndroidの古いバージョンのいくつかの機能の後方互換性のために実装できるすべてを完全に実現しなかったということです。 私はそれらを基礎として、多くの新しいものを追加しました。 たとえば、4.3より前のバージョンで発生した、いくつかの誤った動作のさまざまな修正。 さらに、私のライブラリAPIはAndroid 2.2以降のバージョンと互換性がありますが、4.0より前のバージョンでは、アニメーションなしでシーンの変更(レイアウト)が実行されます。 また、私は最新の状態に保つようにします。 最近、Android 5.0(Lollipop)の新しいバージョンがリリースされ、その中のTransitions APIパッケージ全体のコードも大きく変更されました。 すべての変更をライブラリに投稿しました。
5.0のAPIの新機能
- これで、ViewのTransitionNameを設定できます。 最初のシーンと2番目のシーンで同じビューに同じ名前を付けて、それらの間の遷移をアニメーション化する必要があると言います。 これは、以前は異なるxmlファイルで記述された2つのシーンのビューに同じIDを指定する必要があったため便利です。 5.0では、xmlを使用して説明の属性としてtransitionNameを指定するか、任意のビュー継承でsetTransitionNameメソッドを呼び出して指定できます。 私のライブラリでは、この機能をこのように部分的に移植しました。View継承自体に対して同じではなく、静的メソッドTransitionManager.setTransitionName(View v、String transitionName)を呼び出すことをお勧めします。
- スライド フェードのような可視性の後継である新しいトランジション。 これを使用すると、シーンに表示されるビューを選択したエッジから「実行」できます。 新しいスライド(Gravity.LEFT)の例):

- 爆発する 多くの点でスライドと似ていますが、ビューは、いわゆる遷移エピセンター(setEpicenterCallbackメソッドを参照)を使用して設定される特定の方向から、またはこのエピセンターが指定されていない場合はランダムな角度から実行されます。
- TransitionPropagation。 アニメーションの開始の遅延について説明します。 たとえば、CircularPropagationをインストールすると、ビューが設定された震源地に近づくほど、アニメーションが早く開始されます。 setPropagationパラメーターを使用して遷移に設定します。
Explode TransitionとCircularPropagationがインストールされたFrameLayoutからすべてのビューを削除する例(画面上のタパポイントは震源地です):

- ChangeImageTransform 。 遷移。ImageView内の画像のマトリックス遷移をアニメーション化します。 これを使用すると、画像をスムーズにサイズ変更およびスケーリングできます。 例を見てみましょう。 左側の若い女性はChangeBoundsおよびChangeImageTransformの操作を受け、右側の少女はChangeBoundsのみを取得しました。 肉眼で見ると、アニメーションの開始時に正しいものがどのように「ぴくぴくする」かがわかります。

- ChangeClipBounds 。 ビューのclipBoundsパラメーターのスムーズな変更。 しかし! setClipBoundsメソッドはAndroid 4.3でのみ登場したため、このバージョンからのみこのパラメーターを変更してアニメーション化することができます。 例:

- パス(曲線)モーション 。 これで、 setPathMotionメソッドを使用して、任意の遷移の2つの座標で構成されるパラメーターの座標を計算するためのルールを設定できます。 たとえば、x座標とy座標を変更する場合、Viewは新しい座標まで直線ではなく円弧で実行できます。 これがどのように見えるかの例を与えるには、 それについての良い記事へのリンクを与えるだけです。
- 他に何が登場したかについては少しですが、今のところ移植することはできません。
アクティビティの移行 。LollipopとMaterial Designの発表でGoogleから広く知られています。 どうやら、多くのロジックがアクティビティ自体に隠されているため、特別なフラグを設定する必要さえあります。 したがって、直接移植するのはそれほど簡単ではありません。 Fragment Transitionと同じ状況。
ChangeTransformと呼ばれる新しいトランジションは、ChangeImageTransformに類似していますが、すべてのビューにマトリックス変換を使用します。
対象
どのトランジションでも、多くの要素、つまり適用される目標を設定できます。
これは、Transitionクラスのメソッドを使用して行われます。
- addTarget (ターゲットの表示)-アクションを適用するビューを明示的に設定します
- addTarget (int targetId)-idビュー
- addTarget (String targetName) -TransitionManager.setTransitionNameで対応する名前が指定されたビューにのみ適用されます
- addTarget (クラスtargetType)-特定のタイプのビューにのみ適用されます。 例:android.widget.TextView.class
以前に追加された目標を削除する方法:
- removeTarget (ターゲットを表示)
- removeTarget (int targetId)
- removeTarget (文字列targetName)
- removeTarget (クラスターゲット)
「すべてを除く」アクションを適用できる方法:
- excludeTarget (ビューターゲット、ブール型除外)
- excludeTarget (int targetId、boolean exclude)
- excludeTarget (クラスタイプ、ブール型除外)
- excludeTarget (クラスタイプ、ブール型除外)
特定のレイアウトのすべての子を除外できるメソッド:
- excludeChildren (表示ターゲット、ブール型除外)
- excludeChildren (int targetId、boolean exclude)
- excludeChildren (クラス型、ブール型除外)
xmlを介して遷移を設定する
遷移自体は、xmlファイルからロードできます。
res / animフォルダーに配置します。 例
<?xml version="1.0" encoding="utf-8"?> <transitionSet xmlns:app="http://schemas.android.com/apk/res-auto" app:transitionOrdering="together" app:duration="400"> <changeBounds/> <changeImageTransform/> <fade app:fadingMode="fade_in" app:startDelay="200"> <targets> <target app:targetId="@id/transition_title"/> </targets> </fade> </transitionSet>
他の3つの遷移で構成される操作のTransitionSetセットを作成しました。 同時に、以前は考慮されていなかった
startDelayプロパティ(アニメーションの開始までの遅延時間)をここで適用しました。 コードから呼び出すためのアナログは、
Transition.setStartDelay (long startDelay)です。
TransitionManager全体をxmlファイルから読み込むことができます。このファイルには、発生する順序に応じてシーンを変更するためのさまざまなルールを記述できます。 簡単な例:
<?xml version="1.0" encoding="utf-8"?> <transitionManager xmlns:app="http://schemas.android.com/apk/res-auto"> <transition app:toScene="@layout/scene3" app:transition="@anim/scene3_transition"/> </transitionManager>
ご注意上記の2つの例は、私のTransitions Everywhereライブラリで動作するように調整されています。 システムTransition APIを使用する場合、xmlファイルを
res / transitionディレクトリに配置する必要があり、すべての属性について、
appの代わりに
android:ネームスペースを使用する必要があります
。カスタムトランジション
これらのトランジションがどれだけクールかを見るために、独自のトランジションを書きましょう。
TextViewのフォントサイズをアニメーション化するとします。
(コメントで提案されているように、この例は、アニメーション中にrequestLayout()が発生するプロパティをアニメーション化するべきではないため、現実から少し引き裂かれています。)captureStartValues、captureEndValues、およびcreateAnimatorメソッドをオーバーライドする必要があります。 最初の2つは、シーンを変更する前後に必要なビューパラメーターの値を取得する役割を果たします。 実際、createAnimatorメソッドは、このパラメーター変更用のアニメーターを作成します。
private class TextSizeTransition extends Transition {
結果:

PS
Androidにスムーズな移行を追加してください!
もう一度、ライブラリへのリンク:
github.com/andkulikov/transitions-everywhere