40

我想为片段的移除设置动画。

我试过:

getSupportFragmentManager().beginTransaction()
    .setCustomAnimations(R.anim.push_down_in, R.anim.push_up_out)
    .remove(myFragment)
    .commit();

但片段只是消失了。

我注意到 out 动画只播放“替换”,所以我尝试用一​​个空片段替换片段,如下所示:

getSupportFragmentManager()
    .beginTransaction()
    .setCustomAnimations(R.anim.push_down_in, R.anim.push_up_out)
    .replace(viewId, new Fragment())
.commit();

但它仍然只是消失消失了。

那么,如何为片段的移除设置动画呢?

4

12 回答 12

20

当我遇到类似问题时,我看到了这一点,只是想我会快速记下。

我认为您应该为当前的片段视图设置动画,而不是创建一个虚拟片段来替换现有片段。动画完成后,您可以简单地删除片段。

我就是这样做的:

final FragmentActivity a = getSherlockActivity();

if (a != null) {
    //Your animation
    Animation animation = AnimationUtils.loadAnimation(a, R.anim.bottom_out);
    animation.setDuration(getResources().getInteger(android.R.integer.config_shortAnimTime));

    //You can use AnimationListener, MagicAnimationListener is simply a class extending it.
    animation.setAnimationListener(new MagicAnimationListener() {
        @Override
        public void onAnimationEnd(Animation animation) {
            //This is the key, when the animation is finished, remove the fragment.
            try {
                FragmentTransaction ft = a.getSupportFragmentManager().beginTransaction();
                ft.remove(RestTimerFragment.this);
                ft.commitAllowingStateLoss();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });

    //Start the animation.  
    getView().startAnimation(animation);
}
于 2013-08-11T08:10:12.933 回答
19

我想到了。

退出视图在进入视图的画布上进行动画处理,因此如果没有进入画布,则没有用于动画的画布。

为了显示动画,我必须始终使用替换并使用与退出的相同大小的输入片段。动画完成后,我将新片段的视图设置为消失。

于 2012-12-22T01:09:36.360 回答
13

您可以通过将此自定义动画设置为 fragmentTransaction 来为移除设置动画

        fragmentTransaction.setCustomAnimations(R.anim.right_in, R.anim.defff,R.anim.defff,R.anim.right_out);

第三个和第四个参数用于删除片段

于 2015-09-07T09:52:30.413 回答
2

我从 Zoltish answer 得到灵感,这是我的实现:

1.在片段中添加这个方法,它会将片段动画到屏幕左侧:

public void animateOut()
{
    TranslateAnimation trans=new TranslateAnimation(0,-300*Utils.getDensity(getActivity()), 0,0);
    trans.setDuration(150);
    trans.setAnimationListener(new Animation.AnimationListener() {

        @Override
        public void onAnimationStart(Animation animation) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onAnimationEnd(Animation animation) {
            // TODO Auto-generated method stub
            ((BetsActivty)getActivity()).removeFrontFragmentAndSetControllToBetting();
        }
    });
    getView().startAnimation(trans);
}

onAnimationEnd() 内部的方法像这样删除片段:

getSupportFragmentManager().beginTransaction().
        remove(getSupportFragmentManager().findFragmentById(R.id.fragment_container)).commit();

2.从活动的onBack()调用片段的animateOut。

干杯

顺便说一句,我的 getDensity() 是:

public static int getDensity(Context context)
{
    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    return (int)metrics.density;
}

我用它计算当前运行设备的 DP 值。

于 2015-01-12T06:48:04.643 回答
2

在插入下一个片段之前用一个空片段替换,并延迟下一个片段的插入(200ms),以便可以播放空白片段的退出动画,解决了我的问题。

这是插入带有退出动画的空片段的代码。

getSupportFragmentManager()
                        .beginTransaction()
                        .setCustomAnimations(R.anim.exit, R.anim.pop_exit)
                        .replace(R.id.fragmentLayout, new Fragment())
                        .commit();

退出.xml

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

</set>

pop_exit.xml

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

</set>
于 2016-02-14T08:59:09.807 回答
2

我同意 hugoc 和这里的一些代码来解决它

public class MyActivity extends Activity {
    //Some thing
    public void Fragment2BackToFragment1(Fragment fragment1, Fragment fragment2) {
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction ft = manager.beginTransaction();
        animateExit(fragment2);
        ft.replace(R.id.main_content, fragment1, "fragment1");
        ft.commit();
    }
    private void animateExit(Fragment exitFragment) {
        if (exitFragment != null) {
            final View view = exitFragment.getView();
            if (view != null) {
                int anim = R.anim.fade_out;
                Animation animation =
                    AnimationUtils.loadAnimation(getActivity(), anim);
                animation.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {

                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        view.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                view.setVisibility(View.GONE);
                            }
                        }, 300);
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {


                    }
                });
                view.startAnimation(animation);
            }
        }
    }
}
于 2017-08-02T10:29:13.200 回答
1

@hugoc 说的原因

退出视图在进入视图的画布上进行动画处理,因此如果没有进入画布,则没有用于动画的画布。

为了显示动画,我必须始终使用替换并使用与退出的相同大小的输入片段。动画完成后,我将新片段的视图设置为消失。

以下是实际代码:

FragmentManager manager = getSupportFragmentManager();
    FragmentTransaction transaction = manager.beginTransaction();
    transaction.setCustomAnimations(R.anim.slide_in_bottom, R.anim.slide_out_top);
    transaction.hide(removeFragment).add(R.id.fragment_container,addFragment).commit();
    transaction = manager.beginTransaction();
    transaction.remove(removeFragment).commit();
于 2016-01-31T17:07:50.997 回答
1

下面是一个简单的修复:

1-在 fragment.getView() 上调用动画。

2-删除 onAnimationEnd() 中的片段。

final Fragment frag= getSupportFragmentManager().findFragmentById(R.id.fragmentContainer);
        frag.getView().animate().alpha(0f).scaleX(0f).scaleY(0f)

                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        getSupportFragmentManager()
                                .beginTransaction()
                                .remove(frag)
                                .commit();
                    }
                }).start();
于 2018-08-12T23:08:35.673 回答
0

输入内容:
必须显示的新片段

什么退出:
必须隐藏的是当前片段

什么 popEnter:
它是必须显示的前一个片段

什么 popExit:
必须隐藏的当前片段

要使用这些动画,您应该将它们定位在显示或隐藏事务命令上。退出动画不适用于删除/替换过​​程。

于 2016-11-30T05:43:35.993 回答
0

setCustomAnimations(enter, exit, popEnter, popExit)支持进出动画,所以设置四个动画,必须在transaction.replace()之前保留

科特林:

    val manager = supportFragmentManager
    val transaction = manager.beginTransaction()
    transaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right ,
            android.R.anim.slide_in_left, android.R.anim.slide_out_right)
    transaction.commit()
于 2018-11-08T11:53:11.673 回答
0

所以简单的方法:

当您打开一个片段(从父 Activity 调用)时:

    FragmentA fragment = new FragmentA();
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.setCustomAnimations(R.anim.slide_up, R.anim.slide_down);
    transaction.add(android.R.id.content, fragment);
    transaction.addToBackStack(null);
    transaction.commit();

指定进入和退出事务

transaction.setCustomAnimations(R.anim.slide_up, R.anim.slide_down);

关闭片段时(从片段内部调用)

getActivity().getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.slide_up, R.anim.slide_down).remove(this).commit();

指定进入和退出事务

setCustomAnimations(R.anim.slide_up, R.anim.slide_down)

于 2018-12-13T07:12:56.030 回答
0

在https://developer.android.com/training/basics/fragments/animate中查看不同的动画变体。

在任何事件(按钮单击、超时等)上,您都可以在片段中编写:

parentFragmentManager.beginTransaction()
    .setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right)
    .remove(this)
    .commitAllowingStateLoss()
// parentFragmentManager.popBackStack() - might be needed if the fragment keeps visible after removing.
于 2020-10-09T12:35:19.040 回答