动画片段之间的过渡


284

我正在尝试动画片段之间的过渡。我从以下Android片段和动画中得到了答案

FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);

DetailsFragment newFragment = DetailsFragment.newInstance();

ft.replace(R.id.details_fragment_container, newFragment, "detailFragment");

// Start the animated transition.
ft.commit();

还有我的R.anim.slide_in_left

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate android:fromXDelta="50%p" android:toXDelta="0"
            android:duration="@android:integer/config_mediumAnimTime"/>
       <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
            android:duration="@android:integer/config_mediumAnimTime" />
</set>

但是当我尝试这个时

02-08 16:27:37.961: ERROR/AndroidRuntime(1717): FATAL EXCEPTION: main
02-08 16:27:37.961: ERROR/AndroidRuntime(1717): java.lang.RuntimeException: Unknown animator name: translate
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.animation.AnimatorInflater.createAnimatorFromXml(AnimatorInflater.java:129)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.animation.AnimatorInflater.createAnimatorFromXml(AnimatorInflater.java:126)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.animation.AnimatorInflater.createAnimatorFromXml(AnimatorInflater.java:93)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.animation.AnimatorInflater.loadAnimator(AnimatorInflater.java:72)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.FragmentManagerImpl.loadAnimator(FragmentManager.java:621)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:733)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:919)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.BackStackRecord.run(BackStackRecord.java:578)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1217)

有任何想法吗?当我检查Honeycomb API参考translate时。我错过了什么?
还有其他方法可以动画化片段之间的过渡吗?谢谢


使用动画师---不是动画!使用android.R.ANIMATOR.fade_in可以正常工作,请勿使用android.R.ANIM.fade_in-它具有行为BUGS
user1269737

Answers:


347

您需要使用新的android.animation与框架(对象动画)FragmentTransaction.setCustomAnimations,以及FragmentTransaction.setTransition

这是一个使用setCustomAnimationsApiDemos的FragmentHideShow.java的示例:

ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);

这是来自res / animator / fade_in.xml的相关动画师XML :

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:interpolator/accelerate_quad"
    android:valueFrom="0"
    android:valueTo="1"
    android:propertyName="alpha"
    android:duration="@android:integer/config_mediumAnimTime" />

请注意,您可以使用组合多个动画师<set>,就像使用旧的动画框架一样。


编辑:由于人们正在询问滑入/滑出的问题,因此我将在此处对此进行评论。

滑入和滑出

你当然可以动画translationXtranslationYx,和y性质,但一般幻灯片涉及动画内容,并从屏幕外。据我所知,没有任何使用相对值的过渡属性。但是,这并不妨碍您自己编写它们。请记住,属性动画只需要对要设置动画的对象(在本例中为view)使用getter和setter方法,因此您可以在view子类上创建自己的 方法getXFractionsetXFraction方法,如下所示:

public class MyFrameLayout extends FrameLayout {
    ...
    public float getXFraction() {
        return getX() / getWidth(); // TODO: guard divide-by-zero
    }

    public void setXFraction(float xFraction) {
        // TODO: cache width
        final int width = getWidth();
        setX((width > 0) ? (xFraction * width) : -9999);
    }
    ...
}

现在,您可以为“ xFraction”属性设置动画,如下所示:

res / animator / slide_in.xml

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/linear_interpolator"
    android:valueFrom="-1.0"
    android:valueTo="0"
    android:propertyName="xFraction"
    android:duration="@android:integer/config_mediumAnimTime" />

请注意,如果要设置动画的对象的宽度与其父对象的宽度不同,则情况看起来将不太正确,因此您可能需要调整属性实现以适合您的用例。


8
我可以使用fade_in和fade_out来工作,但是/ res / animator中的其他人却给出了错误。而且,这些似乎都不适合滑入和滑出。我试图编写自己的xml来做到这一点,但最终我得到的只是片段之上的片段。请问更多帮助吗?
Dave MacLean

那翻译呢?请问如何在objectAnimator中用XML定义百分比值的转换?在使用xml中定义的垂直幻灯片动画进行翻转时,我没有为AdapterViewFlipper制作动画...
GBouerat 2011年

6
我得到11-19 10:27:50.912:W / PropertyValuesHolder(23107):在目标类android.widget.FrameLayout上找不到类型为float的setXFraction()方法。但是在我的XML中,我有自定义视图MyFrameLayout。有任何想法吗?
barkside 2012年

13
实际上,罗曼(Roman)的建议也应该走另一条路:使用支持库时,您需要将旧的动画框架(android.R.anim)与FragmentTransaction.setCustomAnimations一起使用
pjv 2012年

1
@RomanNurik这个答案在大多数设备上效果很好,但是对于某些用户(特别是在某些三星Galaxy S3 / 4手机上),由于某种原因在动画过程中未报告宽度,从而导致片段永远不会出现。我能得到它的工作使用的OnPredrawListener这些用户,如下所示:mavyasoni9891.blogspot.com/2014/06/...
ajpolt

188

我这样做:

添加此方法以用Animations 替换片段

public void replaceFragmentWithAnimation(android.support.v4.app.Fragment fragment, String tag){
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_left);
    transaction.replace(R.id.fragment_container, fragment);
    transaction.addToBackStack(tag);
    transaction.commit();
}

您必须在与resource 关联的anim文件夹中添加 四个动画

enter_from_left.xml

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

exit_to_right.xml

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

enter_from_right.xml

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

exit_to_left.xml

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

输出:

在此处输入图片说明

完成


14
很好的解决方案。但是我不确定为什么您将方向转换为RTL。我的方法:.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right)
zed

2
很棒的解决方案。类似的方法和相同的动画文件可用于活动之间的转换。
Stan,

1
@MikeZriel,res-> anim->将您的xml放在此处
Hiren Patel

3
感谢Hiren,我将速度(700)更改为(300)更好,更像iOS
Mike Zriel

3
大声笑,我回来了解决方案。我正在每个Java类上导入android.app.fragment和FragmentManager。在检查了一些材料之后,我发现使用'setCustomAnimations()'需要导入android.support.v4库。重要的是说应该是“ support.v4.app”!我将所有方法“ getFragmentManager()”替换为“ getSupportFragmentManager()”,并将所有导入文件“ android.app.Fragment / FragmentManager ...”替换为“ android.support.v4.app ....”,然后将其替换为动画开始正常工作而不会崩溃...如果你们在类似情况下陷入困境,请阅读我的解决方案。Thx Hiren Patel xD
KoreanXcodeWorker

58

如果您有能力将自己与棒棒糖联系在一起,然后再使用,似乎可以解决问题:

import android.transition.Slide;
import android.util.Log;
import android.view.Gravity;
.
.
.
f = new MyFragment();
f.setEnterTransition(new Slide(Gravity.RIGHT));
f.setExitTransition(new Slide(Gravity.LEFT));
getFragmentManager()
    .beginTransaction()
    .replace(R.id.content, f, FRAG_TAG)  // FRAG_TAG is the tag for your fragment
    .commit();

希望这可以帮助。


1
尽管这可以在Lollipop上实现,但由于运行Lollipop的设备所占的比例微不足道(目前有1.6%的Android设备正在运行Lollipop),因此几乎不实用。
伊兰·戈尔丁

1
new Slide(...):通话需要API级别21
Chintan Soni

getKey()代表什么?
Alvaro

13
@EranGoldin永无止境..您今天会嘲笑仅使用Android 2.0+的解决方案吗?
汤姆(Tom)

@汤姆,你有意思。但是,当您的应用具有大量用户群时,您不仅会提高API级别。如果此后大多数用户将无法再运行您的应用程序,那根本不是解决方案。
伊兰·戈尔丁

47

Nurik的回答是非常有益的,但我无法得到它的工作,直到我发现了这个。简而言之,如果您使用兼容性库(例如,SupportFragmentManager而不是FragmentManager),则XML动画文件的语法将有所不同。


28

这是片段之间的幻灯片放进/放出动画:

FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.setCustomAnimations(R.animator.enter_anim, R.animator.exit_anim);
transaction.replace(R.id.listFragment, new YourFragment());
transaction.commit();

我们正在使用objectAnimator。

这是动画师子文件夹中的两个xml文件。

enter_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<set>
     <objectAnimator
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:duration="1000"
         android:propertyName="x"
         android:valueFrom="2000"
         android:valueTo="0"
         android:valueType="floatType" />
</set>

exit_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<set>
    <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="1000"
        android:propertyName="x"
        android:valueFrom="0"
        android:valueTo="-2000"
        android:valueType="floatType" />
</set>

希望对您有所帮助。


37
将视图移动2000像素是非常难看的解决方案。
carlo.marinangeli 2015年

4
exit_anim只是为我“弹出”屏幕,它不会在屏幕上重新显示动画。有任何想法吗?我正在使用.setCustomAnimations(R.animator.slide_in_left, R.animator.slide_out_right, R.animator.slide_in_left, R.animator.slide_out_right)
Pablo先生2015年

@MrPablo,其原因可能是您尚未复制粘贴上面的代码。setCustomAnimations应该在replace方法之前调用。
Galya

在这种情况下,如果我用动画替换了其他片段,并且在动画超时或持续时间结束之前立即将应用程序最小化,然后再次返回到应用程序,它将并行显示先前的片段和当前片段。
王子

23

对于其他任何被捕获的人,请确保在构建事务时在调用替换/添加之前调用setCustomAnimations。


12

FragmentTransaction的Android SDK实现需要一个Animator支持库Animation,而不要问我为什么,但是在奇怪的注释之后,我研究了android 4.0.3代码和支持库。Android SDK使用loadAnimator()和支持库使用loadAnimation()


7

尝试使用这种简单而快速的解决方案。Android提供了一些default animation

fragmentTransaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
fragmentManager.addOnBackStackChangedListener(this);
fragmentTransaction.replace(R.id.frame, firstFragment, "h");
fragmentTransaction.addToBackStack("h");
fragmentTransaction.commit();

输出:

在此处输入图片说明


哇..这应该是公认的答案!!一个简单而优雅的解决方案。与其他建议的答案相比,它非常平稳
Chathura Buddhika
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.