片段交易动画完成后执行动作

Posted

技术标签:

【中文标题】片段交易动画完成后执行动作【英文标题】:Performing action after fragment transaction animation is finished 【发布时间】:2012-06-22 15:18:25 【问题描述】:

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

这就是所谓的动画:

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)

有什么方法可以附加一个监听器以知道我的片段何时消失?

【问题讨论】:

【参考方案1】:

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

为了监听 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;
    

【讨论】:

enter 为 false 时不会调用监听器,因为 FragmentManagerImpl 设置了自己的监听器。用 AnimationSet 包装返回它。 @sergio91pt 你能解释一下怎么做吗? @Sheikh Aman 只需创建一个新的 AnimationSet,添加动画(已设置您的侦听器)并返回该集。这只是允许 FragmentManagerImpl 设置另一个侦听器而不覆盖您自己的侦听器。 这应该如何工作?我正在使用此代码,它会在返回原始屏幕并正确设置动画之前闪烁动画。我的代码是:Animation anim = AnimationUtils.loadAnimation(getActivity(), nextAnim); AnimationSet animationWrapper = new AnimationSet(false); animationWrapper.addAnimation(anim); ... return animationWrapper; 您可以通过在进入时返回animation 并在退出时返回animation set 来避免@Merk 方法的闪烁【参考方案2】:

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

例如

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;
       

【讨论】:

我试过这个,但从未调用过onCreateAnimation。我正在使用支持包 v4 中的Fragment,它没有onCreateAnimatior,只有onCreateAnimation。有什么区别吗? 之前没有注意到,但我想那是因为动画师只有 3.0+。您是否正确设置了片段事务,如***.com/questions/4817900/… 所示? 是的,FragmentManager fragmentManager = getActivity().getSupportFragmentManager(); FragmentTransaction ft = fragmentManager.beginTransaction(); ft.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right); ft.addToBackStack(null); ft.replace(R.id.tabContainer, fragment); ft.commit(); fragmentManager.executePendingTransactions(); 我也想做同样的功能..我能够在片段创建时获得事务动画,但是如何在它完成/销毁时提供动画?......运气好吗? 在下面查看我的答案以获得与 Android 支持库兼容的解决方案。【参考方案3】:

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

只需扩展 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();


【讨论】:

我尝试将动画添加到 AnimationSet,但退出时没有调用任何 onAnimation 回调。 为我工作,只添加 AnimationSet【参考方案4】:

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

 FragmentTransaction runOnCommit (Runnable runnable);

例如:

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

【讨论】:

我没有对此进行测试,但是查看文档,当事务提交时,runnable 将运行,而不是在动画完成时运行。即使这样可行,它也只能在事务尚未添加到后台堆栈时使用——这是一个相当大的限制。 @Giuseppe 这将在事务提交后立即执行。你的答案不正确!【参考方案5】:

我必须在 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)
    
    

注意:

父片段必须实现Animation.IAnimationListener 您必须返回一个 AnimationSet 否则 FragmentManager 将覆盖您的侦听器并且不会触发回调。

【讨论】:

以上是关于片段交易动画完成后执行动作的主要内容,如果未能解决你的问题,请参考以下文章

片段交易动画:滑入滑出

无法将其他flas动画片段访问到动作脚本3

UITableView 行动画持续时间和完成回调

十大交易规则,期货界公认圣经

在 UIView beginAnimations 完成后执行操作

Mecanim动画系统