переход общих элементов работает с FragmentTransaction.replace (), но не работает с FragmentTransaction.add ()

Новые переходы общих элементов работают, когда я использую фрагмент «replace», но я не могу заставить его работать фрагмент «добавить». Я использую один и тот же контейнер в обоих случаях.

Подробнее:

Деятельность - макет->

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#00ffff"
    android:orientation="vertical" >

</FrameLayout>

При запуске Activity добавляю на экран Fragment1

getFragmentManager().beginTransaction().replace(R.id.container,new TransitionTestFragment1(), "TransitionTestFragment1").commit();

При событии щелчка для представления в макете Fragment1 -> я добавляю Fragment2 на экран. Я установил слушателя в первом фрагменте onCreateView

public View onCreateView(LayoutInflater inflater, ViewGroup container,
    Bundle savedInstanceState) {
final TransitionSet transitionSet = new TransitionSet();
transitionSet.addTransition(new ChangeImageTransform());
transitionSet.addTransition(new ChangeBounds());
transitionSet.addTransition(new ChangeTransform());
transitionSet.setDuration(300);

View v=inflater.inflate(R.layout.fragment1, null);
final View image=v.findViewById(R.id.image);
image.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        setSharedElementReturnTransition(transitionSet);
        Fragment fragment = new TransitionTestFragment2();
        fragment.setSharedElementEnterTransition(transitionSet);

        FragmentTransaction ft = getFragmentManager().beginTransaction()
                .replace(R.id.container, fragment)
                .addToBackStack("transaction")
                .addSharedElement(image, "MyTransition");
        ft.commit();

    }
});
return v;

}

У меня есть этот вид изображения в макетах обоих фрагментов

 <ImageView
        android:layout_width="300dp" 
        android:layout_height="300dp"
        android:src="@drawable/ic_launcher"
        android:transitionName="MyTransition" />

Теперь переход не работает, если я использую FragmentTransaction.add() для добавления второго фрагмента, но он работает, если вместо этого я использую FragmentTransaction.replace(). Как я могу заставить его работать с помощью add ()? Это вообще возможно?


person Vinay W    schedule 19.03.2015    source источник
comment
Даже я столкнулся с этой проблемой ... Вы нашли решение?   -  person Akshay Mahajan    schedule 16.02.2017
comment
Нет никакого «решения» / обходного пути, о котором я знаю ... поскольку api переходов построен на принципе повторного использования представлений, как указано в ответе @ar34z. Повторное использование может произойти только тогда, когда экран / фрагмент / действие, использующее представление, умирает / приостанавливается, и одно из его представлений может быть повторно использовано на экране, который вот-вот будет запущен. Когда вы добавляете фрагмент, вы не можете повторно использовать его элементы, пока он не умрет.   -  person Vinay W    schedule 29.03.2018


Ответы (3)


Я предполагаю, что это потому, что новый фрагмент помещается поверх старого фрагмента. Старый фрагмент не выводится из контроллера, и onPause (и упорядоченные методы) не вызываются. Он не воспроизводит никаких переходов, потому что старый фрагмент все еще может быть виден пользователю (система этого не знает).

В моем ответе (где вы прокомментировали) я добавил переход для входа и выхода. Если добавить, он вообще оживет? Если нет, то, вероятно, по указанной причине.

person ar34z    schedule 24.03.2015
comment
Нет, он не анимируется, когда я добавляю его в соответствии с вашим ответом. Я вообразил, что причина в этом. Есть ли у вас какие-нибудь идеи, как можно обойтись? В любом случае, я мог бы сделать эту работу, не прибегая к замене «добавить» на «заменить»? В любом случае спасибо за ответ. - person Vinay W; 24.03.2015
comment
Я бы не знал. Я бы сказал, что это невозможно, поскольку система основана на «восстановлении» представления. Я предполагаю, что вы хотите оставить все представления в старом фрагменте такими, какие они есть, и «повторно использовать» одно представление в новом фрагменте. Понятия не имею, насколько сложен ваш новый фрагмент, иначе я бы поместил все в макет «старого» фрагмента, анимируя его сам. Но иногда лучше пойти на уступки (технические или дизайнерские) и либо не анимировать вид, либо иметь причудливую анимацию и без «видимого стека». Если старый фрагмент не остается видимым, зачем использовать добавление, а не замену? - person ar34z; 24.03.2015
comment
думаю, это тоже невозможно. Ищу окончательный ответ, чтобы двигаться дальше. Причина, по которой я не хочу использовать замену, заключается в том, что старый фрагмент выполняет тяжелую работу (загружает значительно большой объем данных для отображения, имеет несколько видов горизонтальной прокрутки) при инициализации .. из-за чего onSaveInstanceState / onRestore .. не достаточно плавно .. тогда как если я просто использую add, все работает плавно (так как ничего не выгружается из основной памяти) - person Vinay W; 24.03.2015

Я знаю, что это старый вопрос, но недавно у меня была такая же проблема: .replace не было вариантом.

Мне пришлось использовать .Hide и .Add, и у меня сработало следующее:

setReorderingAllowed(true) 

по сделке.

person GiampaoloGabba    schedule 20.08.2018
comment
Я пробовал, это сработало, но при выходе из фрагмента анимация перехода не работает, и вид стал невидимым - person JKOU; 11.12.2019

Он не будет анимирован, потому что старый фрагмент все еще присутствует. Для добавления нужно скрыть предыдущий фрагмент. Вот пример

Для толкания:

    fragmentTransaction.add(R.id.content, fragment);
    if (fragments.size() > 0) {
        UIBaseFragment lastElement = fragments.lastElement();
        fragmentTransaction.hide(lastElement);
    }
    fragmentTransaction.addToBackStack(null);
    fragmentTransaction.commit();
    fragments.push(fragment);

Затем поп таким образом

    final FragmentManager manager = getChildFragmentManager();
    manager.popBackStack();
    fragments.pop();
person faiziii    schedule 27.03.2017
comment
Пожалуйста, попробуйте объяснить свой код, и этот код не работает. - person extmkv; 07.06.2017
comment
stackoverflow.com/questions/53179476/ - person Phantom Lord; 14.11.2018