博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android动画-属性动画笔记
阅读量:4100 次
发布时间:2019-05-25

本文共 12582 字,大约阅读时间需要 41 分钟。

什么是属性动画

见名知义,属性动画通过控制对象的属性,(修改控件的属性值)来实现动画效果。属性动画是在Android3.0之后引进的,它非常的强大,可以比较简单的实现许多视图动画做不到的事情。

在使用属性动画之前先来看几个常用的View属性成员:

  • translationX,translationY,translationZ:控制View的位置,值是相对于View容器左上角坐标的偏移。
  • rotationX,rotationY:控制相对于轴心旋转。(0f-> 360f
  • x,y:控制View在容器中的位置,即左上角坐标加上translationX和translationY的值。
  • alpha:控制View对象的alpha透明度值。(0f-> 1f
  • 缩放:水平缩放scaleX,垂直缩放scaleY

ValueAnimator 是ObjectAnimato的父类:

  • ValueAnimator ofInt (int... values):返回一个int型变化的ValueAnimator。
  • ValueAnimator ofFloat (float... values):返回一个float型变化的ValueAnimator。
  • ValueAnimator ofObject (TypeEvaluator evaluator, Object... values):返回一个object型变化的ValueAnimator。
  • ValueAnimator ofArgb (int... values):返回一个颜色值变化的ValueAnimator,API
    LEVEL 21引入。

位移属性动画基本使用

mLinearLayout.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View view) {
ObjectAnimator animator; if(!flag){
animator = ObjectAnimator.ofFloat(mLinearLayout,"translationX",0f,-70f); flag = true; }else {
animator = ObjectAnimator.ofFloat(mLinearLayout,"translationX",0f,0f); //animator.setInterpolator(new OvershootInterpolator()); flag = false; } animator.start(); } });

通过ObjectAnimator的工厂方法ofFloat我们得到一个ObjectAnimator对象,并通过该对象的start()方法,开启动画效果。

ofFloat()方法的第一个参数为要实现动画效果的View,例如这里整体效果的LinearLayout;第二个参数为属性名,也就是前面所说的:translationX,translationY,alpha,rotation,scaleX,scaleY等,这里要实现的是水平平移效果,所以我们采用了translationX;第三参数为可变长参数,第一个值为动画开始的位置,第二个值为结束值得位置,如果数组大于3位数,那么前者将是后者的起始位置。
translationXtranslationY这里涉及到的位移都是相对自身位置而言。
例如: View在点A(x,y)要移动到点B(x1,y1),那么ofFloat()方法的可变长参数,第一个值应该0f,第二个值应该x1-x。

XML布局实现:

在res/animator文件夹下,创建animator_translation.xml文件,内容如下:

ObjectAnimator animator = AnimatorInflater.loadAnimator(this,R.animator.animator_translation); animator.setTarget(mLinearLayout); animator.start();

淡入淡出透明属性动画

mTextView.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View view) {
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mTextView, "alpha",1f,0f,1f); objectAnimator.setDuration(3000); objectAnimator.start(); } });

缩放属性动画基本使用

//第一个参数是控件,第二个是选择什么动画属性 例如 scaleX(x轴缩放),scaleY                ObjectAnimator objectAnimator  = ObjectAnimator.ofFloat(mTextView,                        "scaleX",1f,2f,3f,2f,1f);                objectAnimator.setDuration(3000);//动画持续时间                objectAnimator.setRepeatCount(2);//动画重复次数                objectAnimator.setRepeatMode(ValueAnimator.REVERSE);//动画持续模式 上一次效果反着来                objectAnimator.start();

旋转属性动画基本使用

//ofFloat()方法的可变长参数,如果后者的值大于前者,                // 那么顺时针旋转,小于前者,则逆时针旋转。                ObjectAnimator objectAnimator  = ObjectAnimator.ofFloat(mTextView,                        "rotation",0f,180f,0f,-360f,0f);                objectAnimator.setDuration(3000);//动画持续时间                objectAnimator.start();

AnimatorSet

代码直接利用 AnimatorSet() 如果是XML定义AnimatorSet 利用AnimatorInflater.loadAnimator()加载(使用较少)

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,R.animator.property_animator);set.setTarget(mTextView);set.start();

AnimatorSet可以作用于ObjectAnimator和ValueAnimator,但通常ObjectAnimator用的比较多。

AnimatorSet的相关函数:

  • setInterpolator (TimeInterpolator interpolator),设置之后内部子动画的插值器都是这个
  • setTarget(Object target),设置之后所有内部子动画都作用于相同的target目标对象
  • setStartDelay(long startDelay),它不会覆盖子动画开始延迟,只对AnimatorSet的开始时间起作用,所以它会延后AnimatorSet激活整体动画的开始时间
  • cancle()取消动画,会取消AnimatorSet中的所有子动画。
  • end() 结束动画,会结束AnimatorSet中的所有子动画。
  • getChildAnimations() 获取所有受AnimatorSet控制的动画
  • isStarted(),AnimationSet动画是否开始了,true开始
  • isRunning(),AnimationSet开始之后(isStarted =
    true),内部是否有子动画正在执行,有动画执行返回true
  • pause()暂停动画,
  • resume()恢复暂停的动画
  • play(Animator anim)获取Builder对象

函数 playTogetherplaySequentially的区别:

animatorSet.playTogether(): 多个动画同时执行,可以是对一个对象执行的多个动画,也可以是对多个对象的多个动画。

playTogether(Collection<Animator> items) //利用集合添加动画
playTogether(Animator... items) //利用可变参数添加动画

ObjectAnimator objectAnimator1 = ObjectAnimator.ofArgb(mTextView, "backgroundColor", Color.WHITE, Color.GREEN);                ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(mTextView, "scaleX", 0.1f, 1.2f);                ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(mTextView, "scaleY", 0.5f, 1.0f);                ObjectAnimator objectAnimator4 = ObjectAnimator.ofFloat(mTextView, "translationY", 0, 50);                AnimatorSet animatorSet = new AnimatorSet();                animatorSet.playTogether(objectAnimator1,objectAnimator2,objectAnimator3,objectAnimator4);                animatorSet.setDuration(3000);                animatorSet.start();
效果和animatorSet.playTogether()差不多 PropertyValuesHolder holder1=PropertyValuesHolder.ofFloat("rotation",0f,360f,0f);                PropertyValuesHolder holder2=PropertyValuesHolder.ofFloat("translationX",0f,600f);                PropertyValuesHolder holder3=PropertyValuesHolder.ofFloat("alpha",1f,0f,1f);                ObjectAnimator objectAnimator=ObjectAnimator.ofPropertyValuesHolder(sun,holder1,holder2,holder3);                objectAnimator.setDuration(3000);                objectAnimator.setInterpolator(new OvershootInterpolator());//插值器                objectAnimator.start();

如果多个动画同时对控件的同一个属性进行操作,会按照playTogether添加的最后一个动画覆盖前面操作相同属性的动画,也可能没有覆盖,但确实是最后一个添加的动画起了作用。

playSequentially 顺序播放动画:

playSequentially(List<Animator> items)
playSequentially(Animator... items)
playSequentially是一个动画执行完后执行下一个动画,但如果前一个动画是无限循环,下一个动画永远不会执行。

ObjectAnimator objectAnimator5 = ObjectAnimator.ofFloat(mTextView, "translationY", 200, 450);                ObjectAnimator objectAnimator6 = ObjectAnimator.ofFloat(mTextView, "translationY", 300, 600);                ObjectAnimator objectAnimator1 = ObjectAnimator.ofArgb(mTextView, "backgroundColor", Color.WHITE, Color.GREEN);                ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(mTextView, "scaleX", 0.1f, 1.2f);                ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(mTextView, "scaleY", 0.5f, 1.0f);                ObjectAnimator objectAnimator4 = ObjectAnimator.ofFloat(mTextView, "translationY", 0, 250);                AnimatorSet animatorSet = new AnimatorSet();                //按顺序执行动画                animatorSet.playSequentially(objectAnimator1,objectAnimator2,objectAnimator3,objectAnimator4,objectAnimator5,objectAnimator6);                animatorSet.setDuration(5000);                animatorSet.start();
//实现动画无限循环                objectAnimator1.setRepeatCount(-1);                animatorSet.playTogether(objectAnimator1,objectAnimator2,objectAnimator3,objectAnimator4,objectAnimator5,objectAnimator6);

利用play(Animator)构建Builder对象

Builder play(Animator anim);生成builder对象,Builder能够控制动画的执行顺序和相互之间的依赖。

Builder的函数:

  • public Builder with(Animator anim) 和前面动画一起执行
  • public Builder before(Animator anim) 执行前面的动画后再执行该动画
  • public Builder after(Animator anim) 先执行这个动画再执行前面动画
  • public Builder after(long delay) 延迟n毫秒之后执行动画
//按函数性质执行动画                animatorSet.play(objectAnimator1).with(objectAnimator2).before(objectAnimator3);                animatorSet.setDuration(5000);                animatorSet.start();                   /*                * 链式调用动画执行顺序总结如下:                    Builder链式调用中会先执行after函数中的动画(有多个同时执行),                * 然后执行play和with函数(有多个同时执行)中的动画,                * 最后执行before函数中的动画(有多个同时执行)                * */
动画监听animatorSet.addListener(new Animator.AnimatorListener() {
@Override public void onAnimationStart(Animator animation) {
} @Override public void onAnimationEnd(Animator animation) {
} @Override public void onAnimationCancel(Animator animation) {
} @Override public void onAnimationRepeat(Animator animation) {
}});//需要api19animatorSet.addPauseListener(new Animator.AnimatorPauseListener() {
@Override public void onAnimationPause(Animator animation) {
} @Override public void onAnimationResume(Animator animation) {
}});

ViewPropertyAnimator 动画

//ViewPropertyAnimator 动画,只是针对View对象的特定属性同时播放动画                /*                * 支持属性:                    translationX、translationY、translationZ                    x、y、z                    alpha                    scaleX、scaleY                *                * */                mTextView.animate().translationX(100f).translationY(100f).translationZ(20f).                        setInterpolator(new OvershootInterpolator()).start();
//ViewPropertyAnimator 动画,只是针对View对象的特定属性同时播放动画                ViewPropertyAnimator viewPropertyAnimator  = mTextView.animate();                viewPropertyAnimator.setDuration(2000);                viewPropertyAnimator.translationX(100f);//点击一次向右偏移,之后点击无效果(一次性)               //viewPropertyAnimator.translationXBy(100f);//每次点击都会向右偏移,重复利用                viewPropertyAnimator.start();

估值器与插值器

插值器:根据时间流逝的百分比计算出当前属性值改变的百分比。

正常情况下,默认的插值器已经够用,如果自己数学厉害,想显摆一下,也是通过实现TimeInterpolator接口的getInterpolation()自定义的。
在这里插入图片描述

/** * A time interpolator defines the rate of change of an animation. This allows animations * to have non-linear motion, such as acceleration and deceleration. */public interface TimeInterpolator {
/** * Maps a value representing the elapsed fraction of an animation to a value that represents * the interpolated fraction. This interpolated value is then multiplied by the change in * value of an animation to derive the animated value at the current elapsed animation time. * * @param input A value between 0 and 1.0 indicating our current point * in the animation where 0 represents the start and 1.0 represents * the end * @return The interpolation value. This value can be more than 1.0 for * interpolators which overshoot their targets, or less than 0 for * interpolators that undershoot their targets. */ float getInterpolation(float input);}

估值器:根据当前属性改变的百分比来计算改变后的属性值,移动的位置;

自定义估值器:

//自定义估值器,重写计算规则,多利用数学公式    class BallDownEvaluator implements TypeEvaluator
{
/** * @param fraction 动画执行了的百分比, * * @param startValue 点的起始值 * * @param endValue 点的最终值 * @return * */ @Override public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
//以后可以利用估值器实现更多的曲线动画,比如贝塞尔、正弦余弦动画等。 //抛物线方程式 s=1/2*g*t*t //定义初速度150,加速g=9.8,时间t=5s,就是动画设置的执行时间 float time = 5* fraction* 1.0f; PointF pointF = new PointF(); pointF.x = 150 * time; pointF.y = 0.5f * 98.0f *time *time; return pointF; } }
mTextView.setOnClickListener(new View.OnClickListener() {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override public void onClick(View view) {
//ValueAnimator 是 ObjectAnimator 的父类 //太阳下山抛物线 ObjectAnimator objectAnimator = new ObjectAnimator(); BallDownEvaluator ball = new BallDownEvaluator(); objectAnimator.setDuration(5000); //1.先设置value 位置(0,0) objectAnimator.setObjectValues(new PointF(0,0)); //2.再设置估值器 objectAnimator.setEvaluator(ball); objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override public void onAnimationUpdate(ValueAnimator valueAnimator) {
PointF pointF = (PointF) valueAnimator.getAnimatedValue(); //通过不断的改变view(sun)的坐标来实现抛物线动画 sun.setX(pointF.x); sun.setY(pointF.y); } }); objectAnimator.start(); } });

keyFrame(关键帧)

假如觉得自定义自定义插值器或估值器有难度,也可以使用关键帧Keyframe对象来实现。Keyframe让我们可以指定某个属性百分比时对象的属性值。

Keyframe start = Keyframe.ofFloat(0f,0f);                Keyframe middle1 = Keyframe.ofFloat(0.3f,300f);                Keyframe middle2 = Keyframe.ofFloat(0.7f,600f);                Keyframe end = Keyframe.ofFloat(1f,900f);                PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("translationX",                        start,middle1,middle2,end);                ObjectAnimator.ofPropertyValuesHolder(sun,holder).setDuration(3000).start();

链接:

链接:新小梦 https://juejin.cn/post/6846687601118691341

转载地址:http://phrii.baihongyu.com/

你可能感兴趣的文章
c++输出文件流ofstream用法详解
查看>>
字符编码:ASCII,Unicode 和 UTF-8
查看>>
QT跨MinGW和MSVC两种编译器的解决办法
查看>>
firewalld的基本使用
查看>>
Linux下SVN客户端使用教程
查看>>
i2c-tools
查看>>
Linux分区方案
查看>>
nc 命令详解
查看>>
如何使用 systemd 中的定时器
查看>>
git命令速查表
查看>>
linux进程监控和自动重启的简单实现
查看>>
OpenFeign学习(三):OpenFeign配置生成代理对象
查看>>
OpenFeign学习(四):OpenFeign的方法同步请求执行
查看>>
OpenFeign学习(五):OpenFeign请求结果处理及重试控制
查看>>
OpenFeign学习(六):OpenFign进行表单提交参数或传输文件
查看>>
OpenFeign学习(七):Spring Cloud OpenFeign的使用
查看>>
Ribbon 学习(二):Spring Cloud Ribbon 加载配置原理
查看>>
Ribbon 学习(三):RestTemplate 请求负载流程解析
查看>>
深入理解HashMap
查看>>
XML生成(一):DOM生成XML
查看>>