【问题标题】:Android: How can we backport withEndAction to older versions, with help of Nine Old AndroidsAndroid:在九个旧 Android 的帮助下,我们如何将 withEndAction 向后移植到旧版本
【发布时间】:2016-11-15 12:39:20
【问题描述】:

我正在做一些事情,它需要一个接一个地播放大约 10 个动画,但是在每个动画结束时需要检查一些条件,所以我不能使用动画集或 setStartDelay。

我发现在 Jelly Bean 上使用新方法很容易做到,其中 withEndAction 是我作为实验做的,但现在我必须在具有 minSdk 10 的应用程序中实现它。

我使用的是 Nine Old Android,它运行良好,但使用 setListner 非常困难,并且创建的代码难以维持 10 个连续动画。

所以我在想,创建一个继承自九个旧机器人的适配器,我可以添加执行可运行的 withEndAction 函数?

有人可以指导我如何做到这一点,有没有更好的方法?

谢谢

【问题讨论】:

    标签: android


    【解决方案1】:

    我用setListener

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
            viewPropertyAnimator.setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    doSomething();
                }
            });
        } else {
            viewPropertyAnimator.withEndAction(new Runnable() {
                @Override
                public void run() {
                    doSomething();
                }
            });
        }
    

    【讨论】:

    • 移除 onAnimationEnd() 中的监听器,防止稍后在同一对象上制作动画时再次调用它
    • 也可以去掉 if 语句,直接使用:viewPropertyAnimator.setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { doSomething(); } });
    【解决方案2】:

    您现在可以使用ViewCompat 并附加您想要的任何动画。

    ViewCompat.animate(yourView).scaleY(3).withEndAction(yourRunnable).start();
    

    【讨论】:

      【解决方案3】:

      我能想到的有两种选择:

      1. 使用外观模式创建您自己的动画池(这可能需要大量工作)
      2. 从 ADT 获取源代码并进行修改。如果你找不到它,这里是:http://pastebin.com/9nCPC4aR。将它(类似于ViewPropertyAnimatorCompat)复制到您自己的包中。这个类似乎与其他 Android 东西没有太多的耦合,所以应该按原样工作:)
      3. 更新:这里是另一个选项,动画队列。类似于第一个想法,但更直接一点:

      代码:

      public class AnimationQueue extends LinkedList<Animation> implements
          AnimationListener {
      
      private View mView;
      
      public static AnimationQueue ready(Animation... animations) {
          AnimationQueue queue = new AnimationQueue();
          for (Animation animation : animations) {
              queue.add(animation);
          }
          return queue;
      }
      
      public AnimationQueue steady(View view) {
          mView = view;
          return this;
      }
      
      public void go() {
          Animation animation = poll();
          animation.setAnimationListener(this);
          mView.startAnimation(animation);
      }
      
      @Override public void onAnimationEnd(Animation animation) {
          go();
      }
      
      @Override public void onAnimationStart(Animation animation) {
      }
      
      @Override public void onAnimationRepeat(Animation animation) {
      }
      
      }
      

      用法:

      AnimationQueue.ready(anim1, anim2, anim3).steady(view).go();
      

      干杯

      【讨论】:

      • 感谢您的帮助,第一个似乎很难与我正在尝试做的事情做,我尝试了第二个选项,但它似乎取决于 api 级别 16 的 View 类中的某些功能,你会建议也复制 View 还是有其他解决方案?
      • 然后,把它放在你项目的包android.view中。 (有点hack,但应该可以)使用修改后的名称以避免冲突:) 另外,将构造函数公开或创建静态访问器方法。
      【解决方案4】:

      我的解决方案也在使用神奇的 Nineoldandroids

      相反 的

      starsBig[4].animate().rotation(3600).setDuration(2000).withEndAction(runnable)
      

      我做到了

      animate(starsBig[4]).rotationBy(3600).setDuration(2010);
      this.runOnUiThread(new Runnable() {
      public void run() {
          for (int i = 0; i < 5; i++) {
              starReset(stars[i]);
              starReset(starsBig[i]);
          }
                 }
      });
      

      一个动画效果很好

      【讨论】:

        【解决方案5】:

        我认为我有更好的解决方案:

                    view.animate().setDuration(2000).alpha(0);
                    //timAnimDelay.purge();
                    timAnimDelay.schedule(new TimerTask() {
                        @Override
                        public void run() {
        
                            // on UI thread
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    // here animation
                                }
                            });
                        }
                    // delay start
                    } , 2000);
                    timAnimDelay.purge();
        

        【讨论】:

        • 这里不需要使用定时器任务...只需使用new Handler().postDelayed()。无论哪种方式,这种方法可能不如 Blundell 上面的答案好(动画可能需要比预期运行的时间长一点,例如,如果同时发生多个动画......如果是这种情况,那么它可能在动画能够完成之前执行可运行对象)。
        【解决方案6】:

        基本上,为了使您的代码更具可读性,您可以使用内置的AnimatorListenerAdapter 来将您从匿名的内部类混乱中解救出来。您甚至可以将其抽象化,使其看起来像 withEndAction 这样的:

        import android.animation.Animator;
        import android.animation.AnimatorListenerAdapter;
        import android.app.Application;
        import android.support.v4.view.ViewPropertyAnimatorListener;
        import android.view.View;
        
        
        public class AnimatorActionListener extends AnimatorListenerAdapter {
        
        public enum ActionType {
            START, END;
        }
        
        final private ActionType type;
        final private Runnable action;
        
        public AnimatorActionListener(Runnable action, ActionType type) {
            this.action = action;
            this.type = type;
        }
        
        @Override
        public void onAnimationEnd(Animator animation) {
            if (type == ActionType.END) {
                action.run();
            }
        }
        
        @Override
        public void onAnimationStart(Animator animation) {
            if (type == ActionType.START) {
                action.run();
            }
        }
        }
        

        然后用法变成:

         view.animate()./*...some parameters...*/.setListener(new AnimatorActionListener(new Runnable() {
                @Override
                public void run() {
                    // do stuff
                }
            }, ActionType.END)); // or ActionType.START
        

        对于那些必须使用平台内置函数(withStartAction, withEndAction)的人,只需将SDK检查代码也放在AnimatorActionListener中,以节省客户端类的混乱。

        【讨论】:

          猜你喜欢
          • 2014-08-07
          • 2020-03-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-02-16
          • 1970-01-01
          • 2011-03-31
          相关资源
          最近更新 更多