美文网首页
动画第八步-> AnimatorSet:联合动画的代码实现

动画第八步-> AnimatorSet:联合动画的代码实现

作者: crossroads | 来源:发表于2016-12-21 16:24 被阅读302次
    极客学院Animation教程讲解的很详细,点击进入哦

    这里为学习的整理和补充O(∩_∩)O

    一、概念大述

    想必大家都看到赛马,在赛马开始前,每个马都会被放在起点的小门后面,到点了,门打开,马开始一起往前跑。

    • playTogether 只是一个时间点上一起开始,对于开始后,各个动画怎么操作就是他们自己的事了,至于各个动画结不结束也是他们自已的事了。所以最恰当的描述就是门只负责打开,打开之后马咋跑,门也管不着,最后,马回不回来跟门也没啥关系。门的责任只是到点就打开而已。
      放在动画上,就是在激活动画之后,动画开始后的操作只是动画自己来负责。至于动画结不结束,也只有动画自己知道。
    • playSequentially 的意义就是当一匹马回来以后,再放另一匹。那如果上匹马永远没回来,那下一匹马也永远不会被放出来。
      放到动画上,就是把激活一个动画之后,动画之后的操作就是动画自己来负责了,这个动画结束之后,再激活下一个动画。如果上一个动画没有结束,那下一个动画就永远也不会被激活。

    下面,我们就具体了解一下吧O(∩_∩)O~

    二、基本用法

    public void playSequentially(Animator... items);
    public void playSequentially(List<Animator> items);
    public void playTogether(Animator... items);
    public void playTogether(List<Animator> items);
    

    demo:(标注①②的地方此时忽略,在第三小节讲解)

    //第一步,声明ObjectAnimator对象
    colorOfView1 = ObjectAnimator.ofInt(view1, "backgroundColor", 0xffff00ff, 0xff00ff00);
    translateOfView1 = ObjectAnimator.ofFloat(view1, "translationY", 0, -600);
    //translateOfView1.setStartDelay(5000);③
    translateOfView2 = ObjectAnimator.ofFloat(view2, "translationY", 0, 600);
    rotateOfView2 = ObjectAnimator.ofFloat(view2, "rotation", 0, 300, 200);
    //rotateOfView2.setStartDelay(2000);②
    playSquentlyBtn.setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View v) {
           playSquetially();
       }
    });
    playTogetherBtn.setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View v) {
           playTogether();
       }
    });
    
    //依次播放,一个动画播放完毕后,才执行下一个
    public void playSquetially() {
        animatorSetS = new AnimatorSet();
        animatorSetS.setDuration(3000);
        animatorSetS.playSequentially(translateOfView1, colorOfView1, translateOfView2, rotateOfView2);
        //animatorSetS.setStartDelay(1000);①
        animatorSetS.start();
    }
    
    //一起开始,所有动画同时执行start方法
    public void playTogether() {
        animatorSetT = new AnimatorSet();
        animatorSetT.setDuration(3000);
        //animatorSetT.setTarget(view2);④
       animatorSetT.playTogether(translateOfView1, colorOfView1, translateOfView2, rotateOfView2);
       //animatorSetT.setStartDelay(1000);①
        animatorSetT.start();
    }
    

    执行效果:


    playSequentially
    playTogether

    注意:
    animatorSet.setDuration(3000)将3000这个值赋值给了每个ObjectAnimator对象的setDuration()方法,但是,在API15上AnimatorSet.setDuration()方法并没有给它的子objectAnimator设置解决方案是给每个add到animatorSet中的ObjectAnimator都设置自己的duration。(Android版本兼容问题)

    三、延时这个坑~

    1.将标注为①的代码注释去掉,执行 animatorSet.setStartDelay方法,该方法表示:门在1000ms之后打开,此时,马🐴开始往前跑。
    2.此时,再将②标注的代码注释去掉,执行rotateOfView2.setStartDelay(2000),可以看到如下效果:
    (门在1000ms之后打开,但是旋转动画这匹马等了2000ms才开始跑)


    playSquentially.gif playTogether.gif

    看到这里,可能有人要问了,坑呢?坑在哪里?这些很符合逻辑思维嘛,那接下来就一起踩坑吧Q_Q

    • 咱们将③注释去掉,开始执行(看下边gif),咦?为啥其他马都不跑了?要再多等5000ms才开始跑,明明只有translateOfView1这匹马让他晚了5000ms呀?_?
    playTogether.gif playSquentially.gif

    表急,看下边⤵️:

     AnimatorSet 激活延时 = AnimatorSet.startDelay+第一个动画.startDelay
    

    所以,1000ms+5000ms=6000ms之后,门被打开,然而由于translateOfView1这第一号马被用掉了延时,所以6000ms后直接开始,然而rotateOfView2没有被用掉延时,所以rotateOfView2需要再等2000ms才能执行

    四、其他方法

    1. setTarget方法
    //设置 ObjectAnimator 动画目标控件
    public void setTarget(Object target)
    

    将注释④去掉,就发现所有的动画都在view2上执行了,view1没有了任何的动作。

    2.AnimatorSet.Builder方法【注意注意】

    Builder对象通过play(Animator)建立
    //和前面动画一起执行
     public Builder with(Animator anim)
     //在该动画之前执行前面的动画
     public Builder before(Animator anim)
     //在该动画之后执行前面的动画
     public Builder after(Animator anim)
     //在延迟 n 毫秒之后执行动画 
    public Builder after(long delay)
    

    demo:

    animatorSet.play(anim1).with(anim2).after(anim3); 
    

    //执行结果是anim3执行完毕后,anim1和anim2一起执行,表弄错了-

    3.其他方法
    在 AnimatorSet 中还有几个函数:

    //设置单次动画时长
    public AnimatorSet setDuration(long duration);
    //设置加速器
    public void setInterpolator(TimeInterpolator interpolator)
    //设置 ObjectAnimator 动画目标控件
    public void setTarget(Object target)
    

    注意:在 AnimatorSet 中设置以后,会覆盖单个 ObjectAnimator 中的设置;即如果 AnimatorSet 中没有设置,那么就以 ObjectAnimator 中的设置为准。如果 AnimatorSet 中设置以后,ObjectAnimator 中的设置就会无效。

    4.addListner添加监听

    1、AnimatorSet 的监听函数也只是用来监听 AnimatorSet 的状态的,与其中的动画无关;
    2、AnimatorSet 中没有设置循环的函数,即setRepeatCount(ValueAnimator.INFINITE),所以 AnimatorSet 监听器中永远无法运行到 onAnimationRepeat()中!

    5.cancel()方法取消动画

    参考文献

    android 4.0.x上AnimatorSet.setDuration上的坑

    相关文章

      网友评论

          本文标题:动画第八步-> AnimatorSet:联合动画的代码实现

          本文链接:https://www.haomeiwen.com/subject/puonmttx.html