Android 片段事务动画完成后执行动作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11120372/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 06:04:01  来源:igfitidea点击:

Performing action after fragment transaction animation is finished

androidandroid-fragmentsandroid-animation

提问by Moop

I want to set a buttons visibility after the animation is finished.

我想在动画完成后设置按钮可见性。

That's what calls the animation:

这就是所谓的动画:

android.support.v4.app.FragmentTransaction fAnimation = this.getActivity().getSupportFragmentManager().beginTransaction();
fAnimation.setCustomAnimations(android.R.anim.slide_in_left, R.anim.pull_out_to_left);
if (this.isVisible()) {
    fAnimation.hide(this);
    fAnimation.commit();
}

// code that will be executed when the fragment is gone (after the animation is over)

Is there any way to attach a listener to know when my fragment is gone?

有没有办法附加一个监听器来知道我的片段何时消失?

回答by mjama

The Animators that @nmw implements in his answer were added in API Level 11 and will not work with Fragments as implemented by the Android support library.

@nmw 在他的回答中实现的动画器是在 API 级别 11 中添加的,并且不能与 Android 支持库实现的 Fragments 一起使用。

To listen to Fragment animation events, I extended the support library's Fragmentclass and overrode onCreateAnimation, attaching a custom AnimationListener to the returned Animation object:

为了收听 Fragment 动画事件,我扩展了支持库的Fragment类并覆盖了onCreateAnimation,将自定义 AnimationListener 附加到返回的 Animation 对象:

public class MyFragment extends android.support.v4.app.Fragment {

    private static final String TAG = "MyFragment";

    @Override
    public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {

        Animation anim = AnimationUtils.loadAnimation(getActivity(), nextAnim);

        anim.setAnimationListener(new AnimationListener() {

            @Override
            public void onAnimationStart(Animation animation) {
                Log.d(TAG, "Animation started.");
                // additional functionality 
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
                Log.d(TAG, "Animation repeating.");
                // additional functionality
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                Log.d(TAG, "Animation ended.");
                // additional functionality
            }
        });

        return anim;
    }
}

回答by nmw

You need to subclass Fragment and override onCreateAnimator, then you can load those animations from XML and attach listeners to them.

您需要继承 Fragment 并覆盖 onCreateAnimator,然后您可以从 XML 加载这些动画并将侦听器附加到它们。

E.g.

例如

public class MyFragment extends Fragment
{
    @Override
    public Animator onCreateAnimator(int transit, boolean enter, int nextAnim)
    {
        final int animatorId = (enter) ? R.anim.in_anim : R.anim.out_anim;
        final Animator anim = AnimatorInflater.loadAnimator(getActivity(), animatorId);
        anim.addListener(new AnimatorListenerAdapter()
        {
            @Override
            public void onAnimationStart(Animator animation)
            {
                ...
            }

            @Override
            public void onAnimationEnd(Animator animation)
            {
               ...
            }
        });

        return anim;
   }    

回答by Meanman

Combining the answers above here is a sample I am using successfully with the support library fragments.

在这里结合上面的答案是我在支持库片段中成功使用的示例。

Simply extend the MenuFragment and set the listener to get a callback of what to execute afterwards.

只需扩展 MenuFragment 并设置侦听器以获取之后执行的回调。

public class MenuFragment extends Fragment {

private WeakReference<OnMenuClosedListener> onMenuClosedListener;

@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
    Animation anim = null;
    if (enter) {
        anim = AnimationUtils.loadAnimation(getActivity(), R.anim.anim_slide_in_top);
    } else {
        anim = AnimationUtils.loadAnimation(getActivity(), R.anim.anim_menu_slide_out_top);
        anim.setAnimationListener(new AnimationListener() {
            @Override public void onAnimationStart(Animation animation) {
            }
            @Override public void onAnimationRepeat(Animation animation) {
            }
            @Override public void onAnimationEnd(Animation animation) {
                onMenuClosed();
            }
        });
    }

    // NOTE: the animation must be added to an animation set in order for the listener
    // to work on the exit animation
    AnimationSet animSet = new AnimationSet(true);
    animSet.addAnimation(anim);

    return animSet;
}

private void onMenuClosed() {
    if (this.onMenuClosedListener != null) {
        OnMenuClosedListener listener = this.onMenuClosedListener.get();
        if (listener != null) {
            listener.onMenuClosed();
        }
    }
}

public void setOnMenuClosedListener(OnMenuClosedListener listener) {
    this.onMenuClosedListener = new WeakReference<MenuFragment.OnMenuClosedListener>(listener);
}

/**
 * Callback for when the menu is closed.
 */
public static interface OnMenuClosedListener {

    public abstract void onMenuClosed();

}

}

}

回答by Giuseppe Sarno

Added in API 26 (and in Support Library) you can use

在 API 26(和支持库)中添加,您可以使用

 FragmentTransaction runOnCommit (Runnable runnable);

For example:

例如:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_from_left);
ft.show(YourFragment);
ft.commit();
ft.runOnCommit(() -> Your_Action_Here);

回答by pnavk

I had to do this in Xamarin. My situation was I needed a callback once the fragment animation ended. Here is how I made it work without any flickering (this is C#/Xamarin):

我必须在 Xamarin 中执行此操作。我的情况是片段动画结束后我需要回调。这是我如何让它在没有任何闪烁的情况下工作(这是 C#/Xamarin):

    public override Animation OnCreateAnimation(int transit, bool enter, int nextAnim)
    {
        Animation anim = base.OnCreateAnimation(transit, enter, nextAnim);

        if (anim == null && nextAnim != 0) {
            anim = AnimationUtils.LoadAnimation(Activity, nextAnim);
        }

        anim.SetAnimationListener(this);
        return anim;
    }

    public void OnAnimationEnd(Animation animation)
    {
    }

    public void OnAnimationRepeat(Animation animation)
    {
    }

    public void OnAnimationStart(Animation animation)
    {
    }

Note:

笔记:

  • The parent fragment has to implement Animation.IAnimationListener
  • You have to return an AnimationSetotherwise the FragmentManagerwill override your listener and the callbacks won't fire.
  • 父片段必须实现 Animation.IAnimationListener
  • 您必须返回一个AnimationSet否则FragmentManager将覆盖您的侦听器并且不会触发回调。