Общие элементы, анимированные между фрагментами

Я пытаюсь анимировать 2 простых представления из выбранного элемента в RecyclerView в новый фрагмент. Я просмотрел множество примеров анимации общих элементов из одного Activity в другое Activity, но очень мало примеров анимации общего элемента из одного фрагмента в другой фрагмент в одном и том же Activity. Это почти работает.

Вот моя структура.

Деятельность

- Полный экран Fragment1 с RecyclerView

- Полный экран Fragment2 с подробностями

Когда пользователь выбирает элемент в RecyclerView во Fragment1, я заменяю Fragment1 на Fragment2, который имеет View с общими элементами в нем в разных положениях и размерах.

Есть небольшой трюк, чтобы заставить его работать: вы должны убедиться, что ваше transitionName уникально для каждого элемента в вашем списке, и, конечно, это transitionName должно совпадать с transitionName элемента в Fragment2 для воспроизведения анимации. У меня эта часть работает, когда я выбираю элемент, 2 общих представления анимируются, но не совсем так, как вы ожидаете, делая это между двумя действиями.

Если я выбираю элемент в нижней части экрана, он рисует представление для фрагмента 2 и анимирует 2 общих представления, как если бы они находились в элементе вверху экрана. Тяжело объяснить. Вот несколько картинок

Fragment1 Выбрать элемент внизу списка

Fragment2 Я ожидал, что синяя линия будет анимироваться снизу вверх, но она начинается сверху и растет только по горизонтали.  , я бы ожидал, что желтая линия останется внизу, но будет расти по горизонтали, но она начинается в верхней части экрана и анимируется вниз

В обоих фрагментах я задаю следующие

        setSharedElementEnterTransition(new ChangeBounds());
        setSharedElementReturnTransition(new ChangeBounds());
        setAllowEnterTransitionOverlap(true);
        setAllowReturnTransitionOverlap(true);

Также в их родительской Activity в onCreate () я установил

        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

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


comment
Я не уверен, что понимаю, чего вы пытаетесь достичь. Я предполагаю, что странные желто-синие полосы - это просмотры, о которых вы говорите? Итак, на первом снимке экрана вы нажимаете на элемент и ожидаете, что две соответствующие желто-синие полосы будут анимированы в местах расположения желтых / синих полос во втором фрагменте ... но что происходит вместо этого? Что вы имеете в виду ... он рисует представление для фрагмента 2 и анимирует 2 общих представления, как если бы они находились в элементе вверху экрана? Кроме того, что означают стрелки на втором снимке экрана?   -  person Alex Lockwood    schedule 16.11.2014
comment
Кстати, если вы используете Android Studio, вы можете довольно легко сделать снимок экрана своего приложения (см. эти инструкции) и загрузите его на YouTube (я знаю, что объяснить проблему должно быть сложно).   -  person Alex Lockwood    schedule 16.11.2014
comment
Последний вопрос: происходит ли такое поведение только, когда вы выбираете элементы в нижней части экрана? Например, будет ли это работать должным образом для элементов вверху?   -  person Alex Lockwood    schedule 16.11.2014
comment
Да, если я выберу элемент внизу своего списка, я ожидаю, что синие и желтые полосы начнут анимацию с нижней части экрана. Синий будет перемещать ось y вверх и масштабировать ось y вниз, а также увеличивать ось x, чтобы, наконец, оказаться в окончательном горизонтальном положении вверху экрана. То же самое и с желтой полосой, за исключением того, что она не будет перемещаться очень далеко, поскольку она уже находится в нижней части экрана, она в основном будет просто масштабировать вниз по оси x и масштабировать ось y, чтобы заполнить нижнюю часть экрана по горизонтали. Я сейчас загружаю видео на YouTube, опубликую, когда он будет готов   -  person brockoli    schedule 17.11.2014
comment
Можно было бы более понятно объяснить в терминах систем координат. Поскольку Fragment 1 - это полноэкранный RecyclerView с кучей элементов. Когда я нажимаю на элемент и загружается мой фрагмент 2, он анимируется, как если бы он использовал локальные координаты представления элемента вместо родительского представления (ReclyclerView). Поэтому, если я выберу последний элемент, желтая полоса может начинаться с 750,0 по его локальной системе координат, однако в родительском представлении это фактически что-то вроде 750,1000, поскольку оно находится в нижней части списка.   -  person brockoli    schedule 17.11.2014
comment
Вот ссылка на youtube (через youtubeslow, чтобы замедлить, чтобы было более понятно, что происходит) youtubeslow .com / watch? v = crv71Q4G62k   -  person brockoli    schedule 17.11.2014
comment
Так возникает ли ошибка только при обратном переходе? Похоже, что переход ввода от первого действия ко второму работает нормально?   -  person Alex Lockwood    schedule 17.11.2014
comment
Нет, они оба неверны. Общие элементы должны анимироваться от положения, в котором они находятся на 1-м экране, до положения, в котором они находятся на 2-м экране. В этом случае, если вы внимательно посмотрите, если я выберу нижний элемент (или любой элемент, который не находится прямо вверху), он всегда запускает анимацию с верхней части экрана во втором фрагменте. Он начинается с точки на экране, где общий элемент находится в 1-м фрагменте. Как вы отметили, он также некорректно работает при обратном переходе по тем же причинам.   -  person brockoli    schedule 17.11.2014
comment
Если вы опубликуете свой образец проекта на GitHub (или чем-то подобном), я буду рад взглянуть.   -  person Alex Lockwood    schedule 20.11.2014
comment
Я действительно ценю это. Я выложу его на bitbucket и вскоре опубликую.   -  person brockoli    schedule 21.11.2014
comment
Без проблем. У меня были аналогичные проблемы с переходами активности, и я смог решить большинство проблем с помощью Activity#postponeEnterTransition() и _2 _..., но для Fragments нет эквивалентных методов, поэтому мне любопытно, есть ли другой способ решения проблемы при использовании Fragment переходов ...   -  person Alex Lockwood    schedule 21.11.2014
comment
Вы можете найти мой тестовый проект на bitbucket здесь. bitbucket.org/brockoli/fragmentsharedelements   -  person brockoli    schedule 22.11.2014
comment
Прохладный! Я посмотрю в эти выходные   -  person Alex Lockwood    schedule 22.11.2014
comment
Я только что посмотрел, и мне не повезло ... Мне удалось получить аналогичные вещи, работающие с Activity переходами, но я еще не слишком много возился с переходами фрагментов. Я сделаю еще один шанс сегодня вечером. Похоже, что проблема в том, что переход фрагмента начинается до того, как завершится представление ресайклера и транзакции фрагмента ... либо это, либо имена переходов не устанавливаются достаточно быстро во втором фрагменте.   -  person Alex Lockwood    schedule 22.11.2014
comment
А пока вы можете продолжать упрощать пример, пока не получите что-то, что работает. Например, может быть, вместо того, чтобы совместно использовать два элемента, сначала попробуйте заставить его работать только с одним общим элементом. Намного проще отлаживать переходы, когда вы начинаете с чего-то, что работает правильно, и добавляете к этому ... попытка отладки более сложного примера, который не работает, может стать настоящей головной болью. (Если в этом есть смысл).   -  person Alex Lockwood    schedule 22.11.2014
comment
Я удалил синий вид, поэтому теперь при переходе фрагмента анимируется только оранжевый вид. По-прежнему некорректная анимация. Я немного почистил код и обновил битбакет.   -  person brockoli    schedule 25.11.2014
comment
Кроме того, я добавил orangeId в качестве переменной-члена ко второму фрагменту и установил его перед заменой / фиксацией фрагмента, поэтому идентификатор представления определенно устанавливается в новом фрагменте до его замены, поэтому этого не может быть.   -  person brockoli    schedule 25.11.2014
comment
Возможно, вы захотите переименовать идентификатор R.id.container, который вы определили в своем файле item.xml ... он конфликтует с идентификатором R.id.container, который вы определили для контейнера фрагментов своей активности. Я не думаю, что это имеет какое-то значение, насколько я могу судить, но на всякий случай ...   -  person Alex Lockwood    schedule 25.11.2014
comment
Интересно, есть ли что-то конкретное в RecyclerView, из-за которого это не работает должным образом. Например, возникают следующие вопросы: работает ли он без представления ресайклера? Работает ли это с обычным списком? Хм...   -  person Alex Lockwood    schedule 25.11.2014
comment
Сегодня вечером я попробовал использовать ListView вместо RecyclerView. Такое же поведение. Насколько я могу судить, это не работает так же, как общие элементы между Activity. Я в значительной степени в растерянности.   -  person brockoli    schedule 27.11.2014


Ответы (1)


Наконец-то решил эту проблему! Как оказалось, поскольку представление, которое я разделяю между двумя фрагментами, является дочерним по отношению к другому представлению (RelativeLayout) во втором фрагменте, вам необходимо добавить переход ChangeTransform в свой TransitionSet. Очевидно, ChangeTransform сообщает системе, чтобы она запомнила исходную позицию представления в 1-м фрагменте перед анимацией в новую позицию во 2-м фрагменте. Вот мой обновленный набор переходов. Я также немного очищу код своего тестового проекта и сделаю последний толчок к битбакету на случай, если он поможет другим после меня. Спасибо за всю помощь с этим Алексом и спасибо @ George-mount за ответ на аналогичный вопрос, который подсказал мне это решение.

<?xml version="1.0" encoding="utf-8"?>

<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <changeTransform/>
    <changeBounds/>
</transitionSet>

https://bitbucket.org/brockoli/fragmentsharedelements

person brockoli    schedule 30.11.2014
comment
Ха ... вау. Рад, что ты наконец понял это. Определенно не ожидал, что это будет решение. :) - person Alex Lockwood; 27.12.2014
comment
Большое спасибо! Нужно ли, чтобы у фрагментов был один frameLayout? Я был сбит с толку Как оказалось, потому что представление, которое я разделяю между двумя фрагментами, является дочерним по отношению к другому представлению (RelativeLayout) во втором фрагменте, - person busylee; 10.06.2015
comment
@brockoli, я пробую то же самое - просто два фрагмента находятся в разных активностях. И ваш код в этом случае не работает. Вы бы знали, что делать в таком случае? - person Anand Sainath; 09.01.2016
comment
stackoverflow.com/questions/53179476/ - person Phantom Lord; 14.11.2018