302

我正在尝试为片段之间的过渡设置动画。我从以下
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时。我错过了什么?
有没有其他方法可以动画片段之间的过渡?谢谢

4

9 回答 9

359

您需要使用新的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>,就像使用旧动画框架一样。


编辑:由于人们在询问滑入/滑出,我将在这里对此发表评论。

滑入和滑出

您当然可以为、、 和属性设置动画translationX,但通常幻灯片涉及在屏幕外设置动画内容。据我所知,没有任何使用相对值的转换属性。但是,这并不妨碍您自己编写它们。请记住,属性动画只需要您正在制作动画的对象(在本例中为视图)上的 getter 和 setter 方法,因此您可以在视图子类上创建自己的和方法,如下所示:translationYxy 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" />

请注意,如果您在其中制作动画的对象与其父对象的宽度不同,事情看起来就不太正确,因此您可能需要调整您的属性实现以适应您的用例。

于 2011-02-08T17:22:15.100 回答
205

我已经这样做了:

添加此方法以用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();
}

您必须在与资源关联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>

输出:

在此处输入图像描述

它完成了

于 2015-11-30T06:25:05.257 回答
65

如果您有能力将自己绑在 Lollipop 和以后,这似乎可以解决问题:

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

科特林版本:

f = MyFragment().apply {
    enterTransition = Slide(Gravity.END)
    exitTransition = Slide(Gravity.START)
}
fragmentManager
    .beginTransaction()
    .replace(R.id.content, f, FRAG_TAG)  // FRAG_TAG is the tag for your fragment
    .commit();

希望这可以帮助。

于 2015-01-23T20:19:24.493 回答
46

Nurik的回答非常有帮助,但在我找到这个之前我无法让它工作。简而言之,如果您使用的是兼容性库(例如 SupportFragmentManager 而不是 FragmentManager),则 XML 动画文件的语法会有所不同。

于 2013-03-07T18:30:01.127 回答
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。

这是animator子文件夹中的两个 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>

退出动画.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>

我希望这会对某人有所帮助。

于 2014-10-29T09:08:13.420 回答
25

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

于 2017-02-12T22:14:55.833 回答
14

尝试使用这个简单快速的解决方案。Android提供了一些默认animation的s。

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

输出:

在此处输入图像描述

于 2018-02-27T09:35:56.750 回答
12

FragmentTransaction 的 Android SDK 实现需要一个Animatorwhile 支持库需要一个Animation,不要问我为什么,但在奇怪的评论之后,我查看了 android 4.0.3 代码和支持库。Android SDK使用loadAnimator()和支持库使用loadAnimation()

于 2013-04-20T03:17:26.487 回答
0

为了给这个老问题添加一个更现代的答案,如果你已经转向 Material Design,这可以很容易地使用提供的动作库来完成——更多细节在https://material.io/develop/android/主题/运动

于 2021-07-08T17:52:07.507 回答