web-dev-qa-db-ja.com

共有要素の移行:別のアクティビティにネストされたフラグメントへのアクティビティ

共有要素の遷移をアプリに追加しようとしています。

シナリオは、ユーザーが画像のサムネイルをクリックすると、全画面で画像が表示される別のアクティビティを開きます。

共有ビューがターゲットアクティビティのレイアウト内で直接ホストされている場合、これは正常に機能します。開始/終了アニメーションでスムーズに動作します。しかし、私がfragment内で同様の効果を達成しようとしている場合、これはnestedターゲットアクティビティでは、このアプローチ機能しませんです。面白いのは、エンターアニメーションが表示されないが、エグジットアニメーションが正常に機能していることです。

別のさらに複雑なビュー階層は、ターゲットビュー(ImageView)が、ターゲットアクティビティのフレームレイアウトでホストされるビューページャー内でホストされる場合です。

誰かが同じ問題を抱えていましたか?

編集:クリックリスナーコード

public class OnClickPicture extends OnClickBase {
  private ObjectPicture object;

  public OnClickPicture(Activity_Parent activity, ObjectPicture object) {
    super(activity);
    this.object = object;
  }

  public void onClick(View v) {

    picasso.load(object.getFullUrl()).fetch();
    Intent intent = new Intent(activity, ActivityPicture.class);
    intent.putExtra("picture_object", helper.gson.toJson(object));

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop && v != null) {
      Pair<View, String> p1 = Pair.create(v, "image");
      ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, p1);
      activity.startActivity(intent, options.toBundle());
    } else {
      activity.startActivity(intent);
    }

  }

}
26
Matin Petrulak

遷移が機能する方法では、アニメーションが発生する前に、新しいアクティビティを作成、測定、およびレイアウトする必要があります。これは、アニメーション化するビューを見つけて適切なアニメーションを作成できるようにするためです。

ドキュメントに記載されている のように、FragmentTransaction.commit()が実行する作業はすべてスケジュールされているため、これは発生しません。それはすぐには起こりません。したがって、フレームワークがアクティビティを作成するときに、アニメーション化するビューを見つけることができません。そのため、入口のアニメーションは表示されませんが、出口のアニメーションは表示されます。アクティビティを終了すると、ビューが表示されます。

解決策は非常に簡単です。まず最初に試すことができるのは FragmentManager.executePendingTransactions() です。それでもまだ十分ではないかもしれません。移行フレームワークには別のソリューションがあります。

OnCreate of Activity postponeEnterTransition() で。これは、アニメーションを作成しても安全であるとユーザーが言うまで待機するようにフレームワークに指示します。つまり、ある時点で( startPostponedEnterTransition() を呼び出して)安全であることを伝える必要があります。あなたの場合、それはおそらくフラグメントのonCreateViewにあります。

これがどのように見えるかの例です:

アクティビティB

@Override
protected void onCreate(Bundle savedInstanceState) {
    // etc
    postponeEnterTransition();
}

フラグメントB

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View sharedView = root.findViewById(R.id.shared_view);
    sharedview.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            sharedview.getViewTreeObserver().removeOnPreDrawListener(this);
            getActivity().startPostponedEnterTransition();
            return true;
        }
    });
}

トランジションフレームワークに関する詳細なブログ投稿 を提供してくれたAlex Lockwoodに感謝します。

33
MidasLefko