結論
- 遷移先でも遷移元でもスクロール要素(RecyclerView や ScrollView など)の中の要素に
android:transitionName
を設定しているのならば、スクロール要素 にはandroid:transitionGroup="true"
を設定していないと稀に良くしぬ - CoordinatorLayout と NestedScrollView を組み合わせるケースで、 AppBarLayout に
android:transitionName
が設定された要素があるのならば、 NestedScrollView にandroid:transitionGroup="true"
を設定していないと稀に良くしぬ
詳細
Android には Android Activity Transitions というものがあります。
遷移元と遷移先で共通して表示される要素を利用した遷移アニメーションを実現するものです。
実装方法の詳細はここらへんを見ていていただくとして…。
今回は遷移元と遷移先で以下のような XML を用意しました。
遷移元XML
// RecyclerView で利用するために用意したレイアウト ... <ImageView android:id="@+id/image" android:layout_width="match_parent" android:layout_height="wrap_content" android:scaleType="centerCrop" android:transitionName="image" app:layout_collapseMode="parallax"/> ...
遷移先XML
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" tools:context="tomoya_shibata.example.activity.NextActivity"> <android.support.design.widget.AppBarLayout android:id="@+id/app_bar_layout" android:layout_width="match_parent" android:layout_height="200dp"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collpasing_toolbar_layout" android:layout_width="match_parent" android:layout_height="match_parent" app:contentScrim="@color/colorPrimary" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <ImageView android:id="@+id/image" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" android:transitionName="image" app:layout_collapseMode="parallax"/> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_collapseMode="pin"/> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_behavior="@string/appbar_scrolling_view_behavior"> ...
以上2つのレイアウトをそれぞれ持つ画面同士の遷移アニメーションのために ActivityOptions.makeSceneTransitionAnimation
を使ってコードを書いてあげたのですが、実行時に以下のようなエラーが発生しました。
Pending exception java.lang.IllegalStateException thrown by 'void android.os.MessageQueue.nativePollOnce(long, int):-2' java.lang.IllegalStateException: Unable to create layer for LinearLayout
このエラーで調べてみると、以下の記事を発見。
スクロールするView(ScrollViewとかRecyclerView等)の中に長いCardView(TextViewなどが入って可変の場合など)を入れた状態でActivityOptions.makeSceneTransitionAnimationをしてアクティビティがアニメーションしながら閉じる瞬間に落ちる問題の解決法です。
まさに今回の件ですね。提示されている解決法に従い、遷移元の RecyclerView に android:transitionGroup="true"
を加えてあげてみました。
…が、これだけではエラー解決せず。
最終的な解決のためには、遷移元だけではなく遷移先の NestedScrollView
に対しても同様の対応が必要でした。
遷移先の ImageView
が NestedScrolView
の子要素でないにも関わらず、というのが罠ですね。
実際のスクロールは NestedScrollView
によって行われるものだから、という理由でしょうか?
以下のように android:transitionGroup="true
を加えてあげました。
// 上記の遷移先 XML から抜粋
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:transitionGroup="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
これで OK!