Activity Transitions のドキュメントを読んだのですが、よくわからなかったので実際に試してみました。
コードで有効にする場合
自分で transition を作るときは、これらの親クラスの Visibilityを継承するのがよさそうです。
コードで指定する場合
@android:transition/explode
@android:transition/fade
@android:transition/slide
です。
テーマで指定する場合
Android Developers のドキュメントでは、引数に this しか渡していませんが、引数が1つのメソッドはありません!(2014年12月4日現在)
次のように第2引数に null を指定します。
Fade
Slide
そのためには、どの View が共通として見なせるのか指定する必要があります。
遷移前後両方のActivityで、一意の名前を指定します。
レイアウトで指定する場合は android:transitionName を使います。
以下では、それぞれの Activity のレイアウトで ImageView に android:transitionName="image"を指定しています。
遷移前(activity_main.xml)
android:transitionName に指定した名前を makeSceneTransitionAnimation()でも指定する必要があります。
android:transitionName を使わずにコードで指定することもできます。
コードで指定する場合
テーマで指定する場合
このファイルの中身は次のようになっています。
@android:transition/move
transition リソースの書き方は Transitionクラスに概要があります。
例えば、@android:transition/move の <transitionSet> に android:transitionOrdering="sequential"を指定すると、各アニメーションが順番に行われます。
res/transition/custom.xml
1. window content transitions を有効にする
Activity Transitions を使うには、window content transitions を有効にする必要があります。コードで有効にする場合
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
テーマで有効にする場合 <style name="BaseAppTheme" parent="android:Theme.Material"> <item name="android:windowContentTransitions">true</item> </style>
2. transition を指定する
切り替え時のアニメーションを指定します。用意されているクラスは Explode, Fade, Slideです。自分で transition を作るときは、これらの親クラスの Visibilityを継承するのがよさそうです。
コードで指定する場合
getWindow().setExitTransition(new Explode());
Explode, Fade, Slide に対応するリソースは@android:transition/explode
@android:transition/fade
@android:transition/slide
です。
テーマで指定する場合
<style name="BaseAppTheme" parent="android:Theme.Material"> <item name="android:windowEnterTransition">@android:transition/explode</item> <item name="android:windowExitTransition">@android:transition/explode</item> </style>
3. ActivityOptions を指定して実行
ActivityOptions.makeSceneTransitionAnimation()を使います。Android Developers のドキュメントでは、引数に this しか渡していませんが、引数が1つのメソッドはありません!(2014年12月4日現在)
次のように第2引数に null を指定します。
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this, null).toBundle());
全体としてこんな感じになります。 public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS); getWindow().setExitTransition(new Explode()); setContentView(R.layout.activity_main); findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { gotoSub(); } }); } private void gotoSub() { Intent intent = new Intent(this, SubActivity.class); startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this, null).toBundle()); } }
ExplodeFade
Slide
4. sharedElement を指定する
遷移前の画面の一部が拡大などして、遷移後の画面の一部になるような transition が可能です。そのためには、どの View が共通として見なせるのか指定する必要があります。
遷移前後両方のActivityで、一意の名前を指定します。
レイアウトで指定する場合は android:transitionName を使います。
以下では、それぞれの Activity のレイアウトで ImageView に android:transitionName="image"を指定しています。
遷移前(activity_main.xml)
<RelativeLayout 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" ...> <ImageView android:id="@+id/image" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#cccccc" android:src="@drawable/ic_launcher" android:transitionName="image" /> <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:text="go to SubActivity" /> </RelativeLayout>
遷移後(activity_sub.xml) <RelativeLayout 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" ...> <ImageView android:id="@+id/image" android:layout_width="match_parent" android:layout_height="200dp" android:background="#cccccc" android:src="@drawable/gopher" android:transitionName="image" /> </RelativeLayout>
* わかりやすさのために、遷移前後の ImageView の画像を変えています。 android:transitionName に指定した名前を makeSceneTransitionAnimation()でも指定する必要があります。
public class MainActivity extends Activity { ... private void gotoSub() { ImageView iv = (ImageView) findViewById(R.id.image); Intent intent = new Intent(this, SubActivity.class); startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this, iv, "image").toBundle()); } }
android:transitionName を使わずにコードで指定することもできます。
public class MainActivity extends Activity { ... private void gotoSub() { ImageView iv = (ImageView) findViewById(R.id.image); String sharedElementName = "image"; iv.setTransitionName(sharedElementName); Intent intent = new Intent(this, SubActivity.class); startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this, iv, sharedElementName) .toBundle()); } }
public class SubActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sub); String sharedElementName = "image"; findViewById(R.id.image).setTransitionName(sharedElementName); } }
5. 複数の sharedElement を指定する
複数の View を共通のエレメントとして指定することができます。public class MainActivity extends Activity { ... private void gotoSub() { ImageView iv = (ImageView) findViewById(R.id.image); String sharedElementName = "image"; iv.setTransitionName(sharedElementName); ImageView iv2 = (ImageView) findViewById(R.id.image2); String sharedElementName2 = "image2"; iv2.setTransitionName(sharedElementName2); Intent intent = new Intent(this, SubActivity.class); startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this, new Pair<View, String>(iv, sharedElementName), new Pair<View, String>(iv2, sharedElementName2)) .toBundle()); } }
public class SubActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sub); String sharedElementName = "image"; findViewById(R.id.image).setTransitionName(sharedElementName); String sharedElementName2 = "image2"; findViewById(R.id.image2).setTransitionName(sharedElementName2); } }
6. sharedElement の transition を指定する
sharedElement の transition は setSharedElementEnterTransition()や setSharedElementExitTransition()で指定します。その他の transition には setExitTransition() や setEnterTransition() で指定したものが適用されます。コードで指定する場合
Transition transition = TransitionInflater.from(this).inflateTransition(R.transition.custom); getWindow().setSharedElementExitTransition(transition); getWindow().setSharedElementEnterTransition(transition);
XMLで用意した transition リソースから Transition オブジェクトを作るには TransitionInflaterを使います。 テーマで指定する場合
sharedElement のデフォルトの transition は Theme.Material で指定されており、@android:transition/move になっています。このファイルの中身は次のようになっています。
@android:transition/move
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"> <changeBounds/> <changeTransform/> <changeClipBounds/> <changeImageTransform/> </transitionSet>
changeBounds は View の大きさをアニメーションさせ、changeImageTransform は ImageView にセットされている画像サイズをアニメーションさせます。 transition リソースの書き方は Transitionクラスに概要があります。
例えば、@android:transition/move の <transitionSet> に android:transitionOrdering="sequential"を指定すると、各アニメーションが順番に行われます。
res/transition/custom.xml
<?xml version="1.0" encoding="utf-8"?> <transitionSet xmlns:android="http://schemas.android.com/apk/res/android" android:transitionOrdering="sequential"> <changeBounds /> <changeTransform /> <changeClipBounds /> <changeImageTransform /> </transitionSet>
おまけ: デフォルト設定