共享元素过渡适用于 FragmentTransaction.replace() 但不适用于 FragmentTransaction.add()

Posted

技术标签:

【中文标题】共享元素过渡适用于 FragmentTransaction.replace() 但不适用于 FragmentTransaction.add()【英文标题】:shared element transition works with FragmentTransaction.replace() but doesn't work with FragmentTransaction.add() 【发布时间】:2015-05-22 14:14:26 【问题描述】:

当我使用片段“replace”时,新的共享元素转换可以工作,但我似乎无法让它工作片段“add”。在这两种情况下,我都使用相同的容器。

更多详情:

活动-布局->

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

</FrameLayout>

在启动 Activity 时,我将 Fragment1 添加到屏幕

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

在 Fragment1 布局中的视图的单击事件中 -> 我将 Fragment2 添加到屏幕上。我在第一个 Fragment 的 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_ 
        android:layout_
        android:src="@drawable/ic_launcher"
        android:transitionName="MyTransition" />

现在,如果我使用FragmentTransaction.add() 添加第二个片段,则转换不起作用,但如果我改用FragmentTransaction.replace(),它会起作用。我怎样才能使它与 add() 一起工作?有可能吗?

【问题讨论】:

即使我也面临这个问题...您找到解决方案了吗? 据我所知,没有“解决方案”/解决方法。因为转换 api 是围绕重用视图的原则构建的,如@ar34z 的回答中所述。只有当使用视图的屏幕/片段/活动停止/暂停并且其视图之一可以在即将启动的屏幕中重用时,才会发生重用。当你添加一个片段时,你不能“重用”它的元素,直到它死掉.. 【参考方案1】:

我知道这是一个老问题,但最近我遇到了同样的问题:.replace 不是一个选项。

我必须使用 .Hide 和 .Add ,对我有用的是设置:

setReorderingAllowed(true) 

关于交易。

【讨论】:

我试过了,它有效,但是在退出片段时,过渡动画不起作用并且视图不可见【参考方案2】:

我猜这是因为新片段被放置在旧片段之上。旧片段没有被放在控制器之外,onPause(和序列方法)没有被调用。它不播放任何过渡,因为旧片段可能对用户仍然可见(系统不知道)。

在我的answer(您评论的地方)中,我添加了一个进入和退出过渡。如果添加它,它甚至会动画吗?如果不是,则可能是由于所述原因。

【讨论】:

不,当我根据您的回答“添加”它时它不会动画。我想这就是原因。不过,您对解决方法有什么想法吗?有什么方法可以让我完成这项工作而不必诉诸将“添加”更改为“替换”?无论如何感谢您的回答。 我不知道。我会说这是不可能的,因为该系统是基于“恢复”视图的。我假设您想保留旧片段中的所有视图,并在新片段中“重用”单个视图。不知道您的新片段有多复杂,否则我会将所有内容放在“旧”片段的布局中,自己制作动画。但有时最好做出让步(技术与设计),要么不为视图设置动画,要么拥有精美的动画并且没有“可见堆栈”。如果旧片段不可见,为什么要使用添加而不是替换? 认为它也不可能。寻找一个明确的答案,这样我就可以继续前进。我不想使用替换的原因是因为旧片段在初始化时做繁重的工作(下载大量数据以显示,有多个水平滚动视图)..由于onSaveInstanceState/onRestore..不够平滑..而如果我只使用添加,一切都会顺利进行(因为没有从主内存中卸载)【参考方案3】:

它不会动画,因为旧片段仍然存在。要添加,您需要隐藏上一个片段。这是一个例子

对于推送:

    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();

【讨论】:

请尝试解释您的代码,但该代码不起作用。 ***.com/questions/53179476/…

以上是关于共享元素过渡适用于 FragmentTransaction.replace() 但不适用于 FragmentTransaction.add()的主要内容,如果未能解决你的问题,请参考以下文章

SVG CSS过渡不适用于`use`元素(Chrome)

导航组件共享元素转换适用于输入,但不适用于弹回

片段之间的共享元素转换

如何在片段转换中淡出非共享视图?

Android共享元素过渡——防止共享元素被绘制

TextInputLayout 共享元素过渡问题