【问题标题】: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)

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

【问题讨论】:

    标签: android android-fragments android-animation


    【解决方案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+。您是否正确设置了片段事务,如stackoverflow.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 将覆盖您的侦听器并且不会触发回调。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-28
      • 1970-01-01
      • 1970-01-01
      • 2013-08-18
      • 1970-01-01
      相关资源
      最近更新 更多