web-dev-qa-db-fra.com

Transition d'élément partagé: activité en fragment imbriqué dans une autre activité

j'essaie d'ajouter une transition d'élément partagé dans mon application.

Le scénario est que l'utilisateur clique sur la vignette de l'image qui ouvre une autre activité avec une vue d'image en plein écran.

Cela fonctionne bien si la vue partagée est hébergée directement dans la disposition de l'activité cible. Fonctionne en douceur pour l'animation d'entrée/sortie. Mais lorsque j'essaie d'obtenir un effet similaire dans fragment qui est imbriqué dans l'activité cible, cette approche ne fonctionne pas. Ce qui est drôle, c'est que l'animation d'entrée n'est pas affichée, mais l'animation de sortie fonctionne bien.

Une autre hiérarchie de vues encore plus compliquée est que si la vue cible (ImageView) est hébergée dans le pager de vue qui est hébergé dans la disposition de trame de l'activité cible.

Quelqu'un a-t-il eu le même problème?

Modifier: mon code d'écoute de clic

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

La façon dont les transitions fonctionnent nécessite que la nouvelle activité soit créée, mesurée et présentée avant que des animations ne puissent se produire. C'est pour qu'il puisse trouver la vue que vous souhaitez animer et créer l'animation appropriée.

Dans votre cas, cela ne se produit pas car, comme indiqué dans la documentation , tout ce que FragmentTransaction.commit () fait est de planifier le travail à effectuer. Cela ne se produit pas immédiatement. Par conséquent, lorsque le cadre crée votre activité, il ne peut pas trouver la vue que vous souhaitez animer. C'est pourquoi vous ne voyez pas d'animation d'entrée mais vous voyez une animation de sortie. La vue est là lorsque vous quittez l'activité.

La solution est assez simple. Tout d'abord, vous pouvez essayer FragmentManager.executePendingTransactions () . Ce n'est peut-être pas encore suffisant. Le cadre de transition a une autre solution:

Dans le onCreate of Activity postponeEnterTransition () . Cela indique au framework d'attendre jusqu'à ce que vous lui disiez qu'il est sûr de créer l'animation. Cela signifie que vous devez lui dire que son coffre-fort (en appelant startPostponedEnterTransition () ) à un moment donné. Dans votre cas, ce serait probablement dans les Fragments onCreateView.

Voici un exemple de ce à quoi cela pourrait ressembler:

Activité B

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

Fragment 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;
        }
    });
}

Merci à Alex Lockwood pour ses articles de blog détaillés sur le framework Transitions .

33
MidasLefko