【问题标题】:How to animate fragment removal如何动画片段移除
【发布时间】:2012-12-08 13:37:12
【问题描述】:

我想为片段的移除制作动画。

我试过了:

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

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

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

【问题讨论】:

    标签: android animation fragment


    【解决方案1】:

    我在遇到类似问题时看到了这个,只是想写一个简短的笔记。

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

    这就是我的做法:

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

    【讨论】:

    • 但是你是在哪里做的呢?片段的哪个方法?
    • 无论您想在哪里删除片段。 Fx 当计时器达到 0 或用户按下丢弃时我这样做了。
    • 你可以这样做,但如果你想在 backPress 上向后播放动画怎么办?
    • 片段动画的重点是您不必为视图设置动画
    • 不得不在 2020 年广泛阅读 SherlockActivity。美好的旧时光 :-)
    【解决方案2】:

    我想通了。

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

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

    【讨论】:

    • 我很想听听更多关于这个的信息。我想为删除几个片段制作动画,然后在一段时间后(AsyncTask 处理)在另一组片段中制作动画。我可以简单地创建一个“虚拟”片段,其透明视图与我想要制作动画的原始片段大小相同吗?
    • 是的,我就是这么做的。
    • 没有其他解决办法吗?
    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案4】:

      我从 Zoltish 的回答中得到灵感,这是我的实现:

      1.在fragment中添加这个方法,它会将fragment从屏幕左侧动画出来:

      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.从activity的onBack()调用片段的animateOut。

      干杯

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

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

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

      【讨论】:

      【解决方案5】:

      在插入下一个片段之前用一个空片段替换,并延迟下一个片段的插入(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>
      

      【讨论】:

        【解决方案6】:

        我同意 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);
                    }
                }
            }
        }
        

        【讨论】:

          【解决方案7】:

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

          【讨论】:

            【解决方案8】:

            下面的简单修复:

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

            【讨论】:

              【解决方案9】:

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

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

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

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

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

              【讨论】:

                【解决方案10】:

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

                【讨论】:

                  【解决方案11】:

                  那么简单的方法:

                  当你打开一个片段(从父 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)

                  【讨论】:

                    【解决方案12】:

                    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.
                    

                    【讨论】:

                      猜你喜欢
                      • 2016-02-06
                      • 2015-04-29
                      • 2017-05-18
                      • 1970-01-01
                      • 2011-12-30
                      • 1970-01-01
                      • 2023-04-02
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多