Android 动画机制(二)

Android 动画机制(二)

属性动画(Property animation)

上一篇文章我们介绍了补间动画,最后我们强调了,补间动画只能改变View的绘制效果,View的真实属性是没有变化的,而属性动画可以直接改变View对象的属性值,属性动画的基类Animator 是一个抽象类,所以我们需要集成这个类,并重写其中的方法,Android SDK默认为开发者提供了几个子类。
属性动画的基本属性:

  • android:duration 动画的持续时间
  • android:interpolator 动画的插值器
  • android:repeatMode 动画重复模式
  • android:repeatCount 动画重复次数
  • setFrameDelay() 设置刷新率
  • set标签 设置动画集合
  • android:ordering 动画播放顺序,和set联合使用

AnimatorSet
Animator的子类,用来组合多个Animator,并制定这些Animator 是顺序播放还是同时播放
ValueAnimator
Animator的子类,定义了属性动画的大部分功能,包括计算各个帧的属性值、处理更新事件,按照属性值的类型控制计算规则。’’
ObjectAnimator
ValueAnimator的子类,将属性动画帧的值设置给制定的对象,需要注意,在使用ObjectAnimator时,需要为对象实现setter方法。
如果对象是View ,为了能显示动画效果,在某些情况下需要注册AnimatorUpdateListener监听器,并在回调方法onAnimationUpdate中调用View的invalidate 方法来刷新View的显示。

在代码中的使用方法

ValueAnimator.ofFloat() 和ValueAnimator.ofInt()

		//ofint() /ofFloat 创建动画实例,将传入的多个Int参数进行平滑过渡:此处传入0和1,表示将值从0平滑过渡到1
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f,1f);
        valueAnimator.setDuration(2000);
        valueAnimator.setStartDelay(500);//设置动画延迟播放的时间
        valueAnimator.setRepeatCount(0);
        // ValueAnimator.RESTART(默认):正序重放   ValueAnimator.REVERSE:倒序回放
        valueAnimator.setRepeatMode(ValueAnimator.RESTART);
        // 设置 值的更新监听器
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float curValue = (Float) animation.getAnimatedValue();
                Log.i("PropertyAnimator","curValue=="+curValue);
                //重新绘制布局,实现显示效果的改变,本例并不需要调用requestLayout()
                view.setScaleX(curValue);
                view.requestLayout();
            }
        });
        valueAnimator.start();
XML 配置
<?xml version="1.0" encoding="utf-8"?>
<animator
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:valueFrom="0"   
    android:valueTo="1000"
    android:valueType="intType"
    android:duration="1000"
    android:repeatCount="0"
    android:repeatMode="restart"
    android:startOffset="500"
    android:fillBefore = "true"
    android:fillAfter = "false"
    android:fillEnabled= "true"
    >
</animator>

相关属性介绍:
android:valueFrom:初始值
android:valueTo:结束值
android:valueType:数据类型
android:duration:动画时长
android:startOffset:执行动画前的延时时长
android:fillBefore:动画播放完成后是否恢复到原来的状态,默认为ture。
android:fillAfter:动画播放完成后是否保持当前的状态,默认为false.
android:fillEnabled:是否开启fillBefore,默认为true
android:repeatCount:重复次数
android:repeatMode:重复模式 restart为正序,reverse为倒序

代码中使用方法:

Animator animator = AnimatorInflater.loadAnimator(this, R.animator.property);
 // 设置动画对象
animator.setTarget(imageView);
animator.start();

ValueAnimator.ofObject
ValueAnimator.ofInt和ValueAnimator.ofFloat操作的是int和float类型的数据,而ValueAnimator.ofObject改变的是对象,ValueAnimator.ofObject没有默认的插值器,需要开发者自己去实现TypeEvaluator接口来实现自定义插值器。
这里我们使用前辈们的案列解析:

1.根据需要定义插值器:Point是一个简单的坐标对象,实现set和get方法

public class MyTypeValued implements TypeEvaluator<Point>{
    @Override
    public Point evaluate(float fraction, Point startValue, Point endValue) {
    	// fraction:表示动画完成度(根据它来计算当前动画的值)
        // startValue、endValue:动画的初始值和结束值
       
        //计算X,Y的差值
        float X=endValue.getX()-startValue.getX();
        float Y=endValue.getY()-startValue.getY();
        //计算当前point的数值,根据自己的实际需要,计算X,Y的值,这里简单的实现匀速平移
        //Point point=new Point(fraction*X+startValue.getX(),fraction*Y+startValue.getY());
       
        //模拟抛物线 
        float x = 400 * (fraction*1.5f);    //坐标x = k * t
        float y = 400 * (fraction*1.5f) * (fraction*1.5f);  //坐标x = k * t *t
        Point point=new Point(x,y);
        return point;
    }
}

动画在自定义View中的使用

public class MyView extends View {

    public static final float RADIUS = 100f;// 圆的半径
    private Point currentPoint;
    private Paint mPaint;

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.BLUE);
    }

    // 先在初始点画圆,通过监听当前坐标值(currentPoint)的变化,每次变化都调用onDraw()重新绘制圆,从而实现圆的平移动画效果
    @Override
    protected void onDraw(Canvas canvas) {
        if (currentPoint == null) {
            currentPoint = new Point(RADIUS, RADIUS);
            // 在该点画一个圆
            canvas.drawCircle(RADIUS,RADIUS, RADIUS, mPaint);

            // 创建初始动画时的对象点  & 结束动画时的对象点
            Point startPoint = new Point(RADIUS, RADIUS);// 初始点
            Point endPoint = new Point(700, 1000);// 结束点

            // 创建动画对象 & 设置初始值 和 结束值
            ValueAnimator anim = ValueAnimator.ofObject(new MyEvaluator(), startPoint, endPoint);
            anim.setDuration(5000);

			//通过 值 的更新监听器,将改变的对象手动赋值给当前对象
            anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                	// 将每次变化后的坐标值(估值器PointEvaluator中evaluate()返回的Piont对象值)到当前坐标值对象(currentPoint)
                    currentPoint = (Point) animation.getAnimatedValue();
 					 // 调用invalidate()后,就会刷新View,每次赋值后就重新绘制,从而实现动画效果
                    invalidate();
                }
            });
            anim.start();
        } else {
            float x = currentPoint.getX();
            float y = currentPoint.getY();
            canvas.drawCircle(x, y, RADIUS, mPaint);
        }
    }

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值