Переход общего элемента: действие во фрагмент, вложенный в другое действие

я пытаюсь добавить общий переход элемента в свое приложение.

Сценарий: пользователь щелкает миниатюру изображения, после чего открывается другое действие с полноэкранным просмотром изображения.

Это прекрасно работает, если общий вид размещается непосредственно в макете целевой активности. Плавно работает для анимации входа/выхода. Но когда я пытаюсь добиться аналогичного эффекта внутри фрагмента, который вложен в целевую активность, этот подход не работает. Забавно, что анимация входа не отображается, но анимация выхода работает нормально.

Другая, еще более сложная иерархия представлений заключается в том, что если целевое представление (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);
    }

  }

}

person Matin Petrulak    schedule 26.07.2016    source источник


Ответы (1)


То, как работают переходы, требует, чтобы новое действие было создано, измерено и размещено до того, как может произойти какая-либо анимация. Это делается для того, чтобы он мог найти представление, которое вы хотите анимировать, и создать соответствующую анимацию.

В вашем случае этого не происходит, потому что, как указано в документах, все, что делает FragmentTransaction.commit(), — это планирование работы. Это не происходит сразу. Поэтому, когда фреймворк создает вашу активность, он не может найти представление, которое вы хотите анимировать. Вот почему вы не видите анимацию входа, но видите анимацию выхода. Представление появляется, когда вы покидаете действие.

Решение достаточно простое. Прежде всего, вы можете попробовать FragmentManager.executePendingTransactions(). Этого еще может быть недостаточно. Фреймворк переходов имеет другое решение:

В onCreate действия postponeEnterTransition(). Это говорит фреймворку подождать, пока вы не скажете ему, что безопасно создавать анимацию. Это означает, что вам нужно сообщить ему, что это безопасно (через вызов startPostponedEnterTransition()) в какой-то момент. В вашем случае это, вероятно, будет во фрагментах onCreateView.

Вот пример того, как это может выглядеть:

Действие Б

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

Фрагмент Б

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

Спасибо Алексу Локвуду за его подробные сообщения в блоге о платформе Transitions< /а>.

person MidasLefko    schedule 16.08.2016
comment
Вы также можете добиться этого без добавления OnPreDrawObserver. Просто переопределите onViewCreated в своем фрагменте и вызовите там startPostponedEnterTransition(). - person Daveloper87; 29.01.2017
comment
Идеальное и чистое объяснение. Спасибо - person GvSharma; 25.10.2017
comment
@ Daveloper87 Это зависит от характера общего представления. Если он статически раздут в xml, ваше предложение должно работать. Если для его установки требуется длительная задача или если он добавляется в корень программно, требуется OnPreDetawListener. - person mp501; 14.03.2018