共享元素转换可以使用FragmentTransaction.replace()方法,但无法使用FragmentTransaction.add()方法。

29

当我使用片段 '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_width="match_parent"
    android:layout_height="match_parent"
    android:background="#00ffff"
    android:orientation="vertical" >

</FrameLayout>

应用程序启动时,我将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_width="300dp" 
        android:layout_height="300dp"
        android:src="@drawable/ic_launcher"
        android:transitionName="MyTransition" />

现在,如果我使用FragmentTransaction.add()来添加第二个碎片,过渡效果就不能正常工作,但是如果我改用FragmentTransaction.replace(),就可以正常工作了。我该如何使它使用add()方法也能正常工作?这有可能吗?


1
我也遇到了这个问题...你找到解决方案了吗? - Akshay Mahajan
我不知道有任何“解决方案”/变通方法,因为转换API是建立在重复使用视图的原则上的,正如@ar34z的答案所述。只有当屏幕/片段/活动使用的视图死亡/暂停并且其中一个视图可以在即将启动的屏幕中重新使用时,才能进行重复使用。当您添加片段时,直到它死亡之前,您无法“重复使用”其元素。 - Vinay W
3个回答

6

我知道这是一个老问题,但最近我遇到了同样的问题:无法使用.replace。

我不得不使用.Hide和.Add,对我有用的是设置:

setReorderingAllowed(true) 

在交易中。

我尝试过这个,它有效了,但是当退出片段时,转换动画不起作用,视图变得不可见。 - JKOU

4
我猜是因为新的片段被放置在旧片段之上。旧片段没有被移出控制器,也没有调用onPause(和序列方法)。它不会播放任何转换,因为旧的片段可能仍然对用户可见(系统不知道这一点)。
在我回答中(你在评论中提到),我添加了进入和退出过渡动画。如果你添加了它,它是否会动画?如果没有,那么很可能是因为上述原因。

不,按照你的回答,当我“添加”它时它并没有动画效果。我想这就是原因。你有任何解决方法吗?有没有办法让它工作而不必改用“替换”而非“添加”?无论如何,感谢你的回答。 - Vinay W
我不确定。我认为这是不可能的,因为该系统基于“重用”视图。我假设您希望将旧片段中的所有视图保留原样,并在新片段中“重用”单个视图。如果不知道您的新片段有多复杂,否则我会将所有内容放在“旧”片段的布局中,并自己进行动画处理。但有时候最好做出让步(技术与设计),要么不对视图进行动画处理,要么拥有花哨的动画效果和没有“可见堆栈”。如果旧片段不可见,为什么要使用add而不是replace? - ar34z
2
认为这不可能。正在寻找明确的答案,以便我可以继续前进。我不想使用replace的原因是旧片段在初始化时会执行大量的工作(下载相当大量的数据以显示,具有多个水平滚动视图),因此onSaveInstanceState/onRestore..不够流畅..而如果我只是使用add,一切都可以顺利运行(因为没有从主内存中卸载任何内容)。 - Vinay W

-2

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

对于推送:

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

请尝试解释您的代码,并且该代码无法正常工作。 - extmkv
https://stackoverflow.com/questions/53179476/fragment-to-fragment-animation-with-shared-element-dont-work-as-expected - Phantom Lord

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接