如何在后退栈上反转片段动画?

119

我以为在使用片段时,通过以下代码会使系统在按下后退按钮时反转后退堆栈上的动画:

FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.setCustomAnimations(R.anim.slide_in, R.anim.hyperspace_out);
ft.replace(R.id.viewContainer, new class(), "layout").addToBackStack(null).commit();
6个回答

275

根据自定义动画的Android文档

变更:

ft.setCustomAnimations(R.anim.slide_in, R.anim.hyperspace_out);

至:

ft.setCustomAnimations(R.anim.slide_in, R.anim.hyperspace_out, R.anim.hyperspace_in, R.anim.slide_out );

现在返回堆栈动画-反向进行!


2
顺便说一句,我知道这与你的问题和答案无关,但你能否给我提供一个解释customAnimations的链接? :P - AreusAstarte
2
AreusAstarte:请参见http://developer.android.com/reference/android/app/FragmentTransaction.html#setCustomAnimations(int, int, int, int)。 - mDroidd
嗨,我正在使用内容转换,它运行良好,但是当我按返回并返回到先前的片段时,背景会消失,动画视图也会与先前的视图重叠,有什么方法可以避免这种情况吗? - user3497504

24

使用正确的动画 我已经使用以下动画,并且它像魔法一样起作用

slide_in_left.xml

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

slide_in_right.xml

 <?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@android:integer/config_mediumAnimTime" >

    <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="500"
        android:propertyName="x"
        android:valueFrom="0"
        android:valueTo="1000"
        android:valueType="floatType" />

</set>

slide_out_left.xml

   <set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@android:integer/config_mediumAnimTime" >

    <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="500"
        android:propertyName="x"
        android:valueFrom="0"
        android:valueTo="-1000"
        android:valueType="floatType" />

</set>

slide_out_right.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@android:integer/config_mediumAnimTime" >

    <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="500"
        android:propertyName="x"
        android:valueFrom="-1000"
        android:valueTo="0"
        android:valueType="floatType" />

</set>

在添加片段时,请使用以下内容

setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_left,
                                R.anim.slide_out_right, R.anim.slide_in_right)

而且它将会100%地工作


2
请注意,如果您正在使用支持片段管理器或者您的片段扩展了Fragment的支持版本,则此方法将无法正常工作。 - w3bshark
@w3bshark 如何使用支持库中的 FragmentManagerFragment 来实现此类动画效果? - Daniels Šatcs
2
@DanielShatz 你必须使用翻译而不是ObjectAnimator。例如,slide_in_left.xml应该是:<translate android:fromXDelta="100%" android:startOffset="25" android:toXDelta="0" /> 参见此答案:https://dev59.com/oW435IYBdhLWcg3w4Uas#5151774 - w3bshark
1
我正在尝试在Marshmallow设备上测试(没有尝试其他版本)。但它不起作用。 最终的FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); fragmentTransaction.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right); fragmentTransaction.replace(R.id.fl_right_container, detailFragment); fragmentTransaction.replace(R.id.fl_left_container, subcategoriesFragment, TestActivity.TAG_SUBCATEGORIES_FRAGMENT); fragmentTransaction.commit(); - techtinkerer

14
在我的情况下
fragmentTransaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right, 
                       R.anim.slide_in_right, R.anim.slide_out_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>

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

2
我本来想自己做的,但是我太懒了。然后我说应该有人在StackOverflow上发布这个问题,结果就出现了!哈哈 - F.Mysir
1
之前没有人发布过这个问题,我相信现在是我发表答案的时候了,以帮助那些和我有同样问题的人...哈哈 @F.Mysir - Hoang Nguyen Huu

3
.setCustomAnimations(R.animator.fragment_fade_in,
        R.animator.fragment_fade_out,
        R.animator.fragment_fade_p_in,
        R.animator.fragment_fade_p_out)

使用以下内容替换上述内容:

mFragmentManager.beginTransaction()
    .setCustomAnimations(R.animator.fragment_fade_in,
            R.animator.fragment_fade_out,
            R.animator.fragment_fade_p_in,
            R.animator.fragment_fade_p_out)
    .replace(R.id.main_container, FragmentPlayerInfo.getInstance(data))
    .addToBackStack(FragmentPlayerInfo.TAG)
    .commit();

1
我建议您添加一份说明,解释您的建议如何有所帮助。 - Wtower
2
我不知道为什么它能工作(: ,但是当在replaceaddToBackstack之后添加动画时,它就无法工作了。 - TarikW
3
@TarikW,我有点晚了,但这里的顺序很重要,你需要在调用replace、addToBackStack方法之前先调用setCustomAnimations。 - Muhammad Husnain Tahir

1
这正如Fragment Transaction类中所提到的。
/**
     * Set specific animation resources to run for the fragments that are
     * entering and exiting in this transaction. The <code>popEnter</code>
     * and <code>popExit</code> animations will be played for enter/exit
     * operations specifically when popping the back stack.
     *
     * @param enter An animation or animator resource ID used for the enter animation on the
     *              view of the fragment being added or attached.
     * @param exit An animation or animator resource ID used for the exit animation on the
     *             view of the fragment being removed or detached.
     * @param popEnter An animation or animator resource ID used for the enter animation on the
     *                 view of the fragment being readded or reattached caused by
     *                 {@link FragmentManager#popBackStack()} or similar methods.
     * @param popExit An animation or animator resource ID used for the enter animation on the
     *                view of the fragment being removed or detached caused by
     *                {@link FragmentManager#popBackStack()} or similar methods.
     */
    @NonNull
    public abstract FragmentTransaction setCustomAnimations(@AnimatorRes @AnimRes int enter,
            @AnimatorRes @AnimRes int exit, @AnimatorRes @AnimRes int popEnter,
            @AnimatorRes @AnimRes int popExit);

所以最终你可以使用这样的方法。
 mFragmentManager.beginTransaction()
                        .replace(R.id.container, fragment)
                        .setCustomAnimations(R.anim.slide_left,//enter
                                             R.anim.slide_out_left,//exit
                                             R.anim.slide_right,//popEnter
                                             R.anim.slide_out_right)//popExit
                        .addToBackStack(fragment.toString())
                        .commit();

0

这对我有用!!这段代码适用于片段!如果您想在活动中使用此代码,请删除开头的getActivity()!!

getActivity().getSupportFragmentManager()
        .beginTransaction()
        .setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.fade_out,android.R.anim.slide_in_left, android.R.anim.fade_out)
        .replace(R.id.fragment_container, new YourFragment)
        .addToBackStack(null)
        .commit();

祝你好运!!


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