本文共 5128 字,大约阅读时间需要 17 分钟。
这些天都在说画view,view的一些动画,不知不觉已经2个礼拜了,这篇是讲的之前漏说的ValueAnimator。
先补一下之间没有贴的Property Animation的框架
Animator --ValueAnimator --ObjectAnimator --AnimatorSetAnimatorInflaterKeyframeKeyframeSetPropertyValuesHolderAnimatorListenerAdapter.java TypeEvaluator --IntEvaluator --FloatEvaluator --ArgbEvaluator
其中ObjectAnimator,AnimatorSet,PropertyValuesHolder在我们之前的文章已经说过了,AnimatorInflater有简略的带过(网上有很多例子可以搜下),没有看过的小伙伴们可以看下传送门
先解释下,上面的架构图,让大家能对整体类与类的关系更清晰了解。
1.Animator, ValueAnimator, ObjectAnimator是描述动画的核心类。其中,Animator是父类,它定义了动画开始/结束/暂停/恢复/重复等接口,并实现了公共函数。ValueAnimator和ObjectAnimator是描述动画的具体类
2.Keyframe是关键帧,通过关键帧可以实现较复杂的动画(例如,曲线运动等)。KeyframeSet是关键帧的辅助类。
3.AnimatorUpdateListener中实现了全部的动画监听接口。但是,监听函数体都没有执行任何动作。在我们需要监听动画相应动作时,可以实现Animator提供的接口,也可以继承于AnimatorUpdateListener。(等会就讲这个)
接下来贴下“栗子”代码,我们边说边理解
先贴下包结构
还是我们之前”TF”男孩的那个包,今天的代码还是用java代码实现的并没有使用xml。
贴一下主要实现的两个方法
private void makeValueAnimatorTranslationX() { //创建ValueAnimator对象,并初始化 ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 200, 0); valueAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { LogUtils.d("--->onAnimationStart"); } @Override public void onAnimationEnd(Animator animation) { LogUtils.d("--->onAnimationEnd"); } @Override public void onAnimationCancel(Animator animation) { LogUtils.d("--->onAnimationCancel"); } @Override public void onAnimationRepeat(Animator animation) { LogUtils.d("--->onAnimationRepeat"); } }); //属性变化大监听器 valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int animationorValue = (Integer) animation.getAnimatedValue();LogUtils.d("--->当前进度值: " + animationorValue); imageView.setTranslationX(animationorValue); } }); valueAnimator.setDuration(2000); valueAnimator.setRepeatCount(4); valueAnimator.setRepeatMode(ValueAnimator.RESTART); //绑定需要执行动画的对象 valueAnimator.setTarget(imageView); valueAnimator.start(); } private void makeValueAnimatorScale() { PropertyValuesHolder propertyValuesHolder1 = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 2.0f, 1.0f); PropertyValuesHolder propertyValuesHolder2 = PropertyValuesHolder.ofFloat("scaleY", 1.0f, 2.0f, 1.0f); ValueAnimator valueAnimator=ValueAnimator.ofPropertyValuesHolder(propertyValuesHolder1,propertyValuesHolder2); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float xValue=(float)animation.getAnimatedValue("scaleX"); float YValue=(float)animation.getAnimatedValue("scaleY"); imageView.setScaleX(xValue); imageView.setScaleY(YValue); } }); valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); valueAnimator.setDuration(2000); valueAnimator.setRepeatCount(2); valueAnimator.setRepeatMode(Animation.RESTART); valueAnimator.setTarget(imageView); valueAnimator.start(); }
我们这两个方法,一个是平移效果,一个是放大效果。
这2种实现其实我们前两篇都已经大篇幅相惜的写了代码,那这一部分又有什么区别呢?理由在下面。。。。(掩面而泣)
当然,也是因为这个实现比较麻烦,我第一时间并没有想用这个做平移等效果,ok废话不说,来解释代码
首先我们声明了一个ValueAnimator对象,并且对他进行了赋值,(0, 200, 0),乍看之下和之前的ObjectAnimator差不多。对,没错,ObjectAnimator就是在这上面加工能做的,所以更好用。
Animator.AnimatorListener:
onAnimationStart() —— 动画开始时调用; onAnimationEnd() —— 动画结束时调用; onAnimationRepeat() —— 动画循环播放时调用; onAnimationCancel() —— 动画被取消时调用。不管终止的方式如何,被取消的动画仍然会调onAnimationEnd();
我们可以再动画运行的各个阶段加入我们的业务逻辑。
然后我们给我们的ValueAnimator添加了ValueAnimator.AnimatorUpdateListener()监听器,它可以让我们使用animation.getAnimatedValue()来获取动画之行的进展。
然后我们在他的回调函数中设置了我们的业务逻辑,让大大姐沿着x轴平移imageView.setTranslationX(animationorValue);
再之后就喝之前一样设置时间啊,重复次数什么的
valueAnimator.setDuration(2000);
valueAnimator.setRepeatCount(4); valueAnimator.setRepeatMode(ValueAnimator.RESTART);记得还要把大大姐跟这个动画绑一下
//绑定需要执行动画的对象 valueAnimator.setTarget(imageView);最后start()一下就好了 valueAnimator.start();
那我们再来简单解释下第二个例子,多动画“组合拳”
xy向同时放大
大致代码是差不多的,有2处不尽相同
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
这里我终于加入了庐山真面目的插值器(根据自己需求吧,也可以自定义)下面贴个自定义的栗子:
public class CustomInterpolator implements TimeInterpolator { @Override public float getInterpolation(float input) { input *= 0.8f; return input * input; } }
声明一个类继承TimeInterpolator,再getInterpolation回调中实现自己的业务逻辑即可。
调用类也是valueAnimator.setInterpolator(new CustomInterpolator());
就好了,非常的简便。
Keyframe部分就不做过多解释了,贴几个参考资料,大家可以更好的理解
源码地址:
感谢点个star,谢谢