Shared Elements による画面遷移を API level 21 未満でも実現する方法はありますか？


Shared Elements を動画で実現したいと思っています。

[makeSceneTransitionAnimation](https://developer.android.com/reference/android/app/ActivityOptions.html#makeSceneTransitionAnimation\(android.app.Activity,%20android.util.Pair%3Candroid.view.View,%20java.lang.String%3E...\))
の様に動的に View を共有して Activity の遷移を行いたいのですが、 **API level 21**
未満の場合はどのように実現すればいいでしょうか。

実装方法として Service 等のライフサイクルを横断するストアに View のインスタンスを保持しておき、そのインスタンスを遷移先の View
をすげ替える事で実現できるのではないかと思っていますが、どなたかご存じないでしょうか？

よろしくお願いします。




英語ですが、DevBytes に実装の仕方を説明した動画があります。

[https://www.youtube.com/watch?v=CPxkoe2MraA&list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0&index=75](https://www.youtube.com/watch?v=CPxkoe2MraA&list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0&index=75)

基本的な考え方は、標準の遷移アニメーションを無効化した上で遷移先のアニメーション側で 独自のアニメーションを頑張る形になります。

遷移先でアニメーションさせるための情報として、遷移元の画像の位置と大きさを Intent の extra にいれて startActivity します。
動画の中では以下の様なコードを呼び出し側に記述しています。

[code]

            int[] screenLocation = new int[2];
            v.getLocationOnScreen(screenLocation);
            PictureData info = mPicturesData.get(v);
            Intent subActivity = new Intent(ActivityAnimations.this,
                    PictureDetailsActivity.class);
            int orientation = getResources().getConfiguration().orientation;
            subActivity.
                    putExtra(PACKAGE + ".orientation", orientation).
                    putExtra(PACKAGE + ".resourceId", info.resourceId).
                    putExtra(PACKAGE + ".left", screenLocation[0]).
                    putExtra(PACKAGE + ".top", screenLocation[1]).
                    putExtra(PACKAGE + ".width", v.getWidth()).
                    putExtra(PACKAGE + ".height", v.getHeight()).
                    putExtra(PACKAGE + ".description", info.description);
            startActivity(subActivity);
    
            // Windowアニメーションを無効化
            overridePendingTransition(0, 0);
    
[/code]

呼び出される側では、onCreate で extra を取り出してアニメーションを行うのですが、 ひとつポイントがあります。 onCreate
の段階ではレイアウトが完了していないので、 ViewTreeObserver を使用して描画の直前に処理を挿入してあげるとうまくいきます。

[code]

        if (savedInstanceState == null) {
            ViewTreeObserver observer = mImageView.getViewTreeObserver();
            observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
    
                @Override
                public boolean onPreDraw() {
                    mImageView.getViewTreeObserver().removeOnPreDrawListener(this);
    
                    // ここにアニメーションの処理を記述
    
                    return true;
                }
            });
        }
    
[/code]

動画の中で解説しているコードはこちらからダウンロードできます。

<http://developer.android.com/shareables/devbytes/ActivityAnimations.zip>

コードだけでも参考になるのではないかと思います。




英語ですが、DevBytes に実装の仕方を説明した動画があります。

[https://www.youtube.com/watch?v=CPxkoe2MraA&list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0&index=75](https://www.youtube.com/watch?v=CPxkoe2MraA&list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0&index=75)

基本的な考え方は、標準の遷移アニメーションを無効化した上で遷移先のアニメーション側で 独自のアニメーションを頑張る形になります。

遷移先でアニメーションさせるための情報として、遷移元の画像の位置と大きさを Intent の extra にいれて startActivity します。
動画の中では以下の様なコードを呼び出し側に記述しています。

[code]

            int[] screenLocation = new int[2];
            v.getLocationOnScreen(screenLocation);
            PictureData info = mPicturesData.get(v);
            Intent subActivity = new Intent(ActivityAnimations.this,
                    PictureDetailsActivity.class);
            int orientation = getResources().getConfiguration().orientation;
            subActivity.
                    putExtra(PACKAGE + ".orientation", orientation).
                    putExtra(PACKAGE + ".resourceId", info.resourceId).
                    putExtra(PACKAGE + ".left", screenLocation[0]).
                    putExtra(PACKAGE + ".top", screenLocation[1]).
                    putExtra(PACKAGE + ".width", v.getWidth()).
                    putExtra(PACKAGE + ".height", v.getHeight()).
                    putExtra(PACKAGE + ".description", info.description);
            startActivity(subActivity);
    
            // Windowアニメーションを無効化
            overridePendingTransition(0, 0);
    
[/code]

呼び出される側では、onCreate で extra を取り出してアニメーションを行うのですが、 ひとつポイントがあります。 onCreate
の段階ではレイアウトが完了していないので、 ViewTreeObserver を使用して描画の直前に処理を挿入してあげるとうまくいきます。

[code]

        if (savedInstanceState == null) {
            ViewTreeObserver observer = mImageView.getViewTreeObserver();
            observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
    
                @Override
                public boolean onPreDraw() {
                    mImageView.getViewTreeObserver().removeOnPreDrawListener(this);
    
                    // ここにアニメーションの処理を記述
    
                    return true;
                }
            });
        }
    
[/code]

動画の中で解説しているコードはこちらからダウンロードできます。

<http://developer.android.com/shareables/devbytes/ActivityAnimations.zip>

コードだけでも参考になるのではないかと思います。

