Android - 片段事务上的自定义动画未运行

86

我正在使用支持包v4和Google API 8(Android 2.2)。

它没有给出任何错误或动画。

事务:

FragmentTransaction transaction = manager.beginTransaction();       
transaction.replace(R.id.content, myFragment);
transaction.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);
transaction.commit();

动画:

slide_in_left.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="700"
        android:fromXDelta="-100%"
        android:toXDelta="0%" >
    </translate>
</set>

slide_out_right.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="700"
        android:fromXDelta="0%"
        android:toXDelta="100%" >
    </translate>
</set>

有人知道这里正在发生什么吗?


1
片段直到Honeycomb(API 11,Android 3.0)才被引入。这可能是问题所在,但我认为Eclipse会告诉你的。 - Steve Blackwell
6
这就是我使用支持包的原因。 - adheus
5个回答

267

在我设置动画之前,经理正在对我的事务进行堆叠,因此在没有动画的情况下它会堆叠事务(令人难过但却是真实的),即使我在setCustomAnimations()之后提交事务也会发生这种情况。

解决方案是首先设置动画:

FragmentTransaction transaction = manager.beginTransaction();       
transaction.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);
transaction.replace(R.id.content, myFragment);
transaction.commit();

所以你必须分割语句,避免使用自我返回对象的技巧。 - sherpya
5
许多 Android 方法返回“this”以避免重新输入变量,但是这里的 transaction.something().somethingelse().replace().commit() 暴露了副作用,因此应该单独调用 setCustomAnimations() - sherpya
47
注意,"self returned object trick" 被称为 "方法链(method chaining)"。 - Egor
1
以上的方法链调用肯定有效。我在自己的项目中测试过了。 - MawrCoffeePls
为了在从后退栈中弹出片段时添加动画效果,请使用 transaction.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right, R.anim.slide_in_left, R.anim.slide_out_right); - Justin
值得加一。这对我来说是救命稻草。 很遗憾,五年过去了,问题仍未解决……它被称为事务,有其原因!为什么调用顺序会引起问题? - Majed DH

25

如上所述,单独的语句肯定会起作用。但是这里的诀窍是在设置事务类型(比如addreplace等)之前使用setCustomAnimation,否则它不起作用。因此,应用相同的逻辑,方法链也可以起作用。例如。

getSupportFragmentManager()
        .beginTransaction()
        .setCustomAnimations(R.anim.a_slide_up,
                             R.anim.a_slide_down,
                             R.anim.a_slide_up,
                             R.anim.a_slide_down)
        .add(R.id.root_layout, 
             MyFrag.newInstance())
        .addToBackStack("MyFrag")
        .commit();

把它放在这里,这样喜欢方法链的人会发现它很有用。干杯!


1
我对你使用“点”运算符进行方法链接的方式有点不满。 - Shaishav
1
同意@Shaishav,两年前写了这个答案,现在更新一下..谢谢! - Harisewak

7

我把这里留下是因为它是最受欢迎的问题。我遇到了片段事务不动画的同样问题。罪魁祸首是在包含布局中将属性 android:animateLayoutChanges 设置为 true

我希望这可以帮助某些人节省找解决方案的时间,因为当有不同文件中的嵌套布局时很难注意到它。


动画现在可以工作了,但是出现了新问题——它的动画行为发生了改变。之前它是按预期水平滑动的,现在从角落处扩展开来。 - Sharad Kale

0
另一个原因可能是在提交之前不必要地放置了fragmentTransaction.show()。这会导致一些Android API版本上的弹出转换未显示。

0
对我来说,问题出在使用了Fragment.getChildFragmentManager()。我改用了Fragment.getParentFragmentManager(),然后动画突然就开始工作了。

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