五.属性动画

作者: 大虾啊啊啊 | 来源:发表于2020-02-25 11:07 被阅读0次

一.概念

通过改变对象的属性,完成一系列的动画效果

二.ValueAnimator

1. 概念描述

动画执行类,通过不断控制值 的变化,再不断 手动 赋给对象的属性,从而实现动画效果

  • 创建ValueAnimator对象的核心方法:
    ofInt(int... values)
    属性以整型的数值从开始值变化到结束值
    ofFloat(float... values)

2.示例

 //1.设置属性的初始值和结束值
        ValueAnimator valueAnimator = ValueAnimator.ofInt(0,500);
        //2.设置动画的时长 2S
        valueAnimator.setDuration(2000);
        //3.设置动画播放次数 重复播放
        valueAnimator.setRepeatCount(-1);
        //4.设置动画的监听器,根据属性的变化,给button重新赋值
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                //5.获取变化之后某一时刻的值
                int value = (int) valueAnimator.getAnimatedValue();
                //6.重新赋值给对象,重装绘制Button
                button.getLayoutParams().width = value;
                //重新绘制,刷新视图
                button.requestLayout();
            }
        });
       valueAnimator.start();

属性以浮点型的值从开始值变化到结束值
ofObject(TypeEvaluator evaluator, Object... values)
属性以某个对象变化到某个对象,TypeEvaluator 为估值器,需要自定义估值器

package com.example.wangyiyunclass;

import android.animation.TypeEvaluator;

public class PointTypeEvaluator implements TypeEvaluator {
    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        // startValue开始值
        // endValue结束值
        // fraction 变化完成程度
        //根据startValue  endValue fraction 计算当前的 x,y
        Point start = (Point) startValue;
        Point end = (Point) endValue;


        float x = start.getX()+fraction*(end.getX()-start.getX());

        float y = start.getY()+fraction*(end.getY()-start.getY());

        //返回当前变化之后的对象
        return new Point(x,y);
    }
}

package com.example.wangyiyunclass;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

public class PotinView extends View {
    private Paint paint;
    public PotinView(Context context) {
        this(context,null);
    }

    public PotinView(Context context, @Nullable AttributeSet attrs) {
        this(context,null,0);
    }

    public PotinView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
    }
    Point point;
    private void init() {
        paint = new Paint();
        paint.setColor(Color.BLUE);
        Point point1 = new Point(100,100);
        Point point2 = new Point(1000,1500);

        ValueAnimator valueAnimator = ValueAnimator.ofObject(new PointTypeEvaluator(),point1,point2);

        valueAnimator.setRepeatCount(-1);
        valueAnimator.setDuration(3000);

        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                 point = (Point) animation.getAnimatedValue();
                invalidate();

            }
        });
        valueAnimator.start();

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(point.getX(),point.getY(),100,paint);

    }
}

三.ObjectAnimator

1. 概念描述

动画执行类,通过不断控制值 的变化,自动 赋给对象的属性,从而实现动画效果

2. 示例


        //button的 透明度从 1 - 0 - 1
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(button,"alpha",1f,0f);
        objectAnimator.setDuration(3000);
        objectAnimator.start();
        objectAnimator.setRepeatCount(-1);

ObjectAnimator的ofFloat(Object target, String propertyName, float... values) 方法中的第二个参数propertyName参数作用是根据propertyName参数,找到对应属性名的set get方法,从而对对象属性进行赋值。比如上面的alpha,即找到对象的setAlpha 和 getAlpha,进行赋值。然后执行动画。

  • 自动赋值的逻辑:
    初始化时,如果属性的初始值没有提供,则调用属性的 get()进行取值;
    当 值 变化时,用对象该属性的 set()方法,从而从而将新的属性值设置给对象属性。

五.差值器(Interpolator)

1.简介

  • 设置属性值从初始值过滤到结束值的变化规律,即确定了动画的变化模式
  • 例如:匀减速,匀加速,先减速后加速,先加速后减速,匀速等等。

2.应用举例

实现非线性运动的动画效果(动画的速率不是一成不变的,可能有加速、减速)

3.具体使用

             //1.创建透明动画对象
                Animation animation = new AlphaAnimation(1, 0);
                //2.创建插值器
                Interpolator interpolator = new OvershootInterpolator();
                //3.给动画设置插值器
                animation.setInterpolator(interpolator);
                //4.播放动画
                ivOne.startAnimation(animation);

以上我们用到了OvershootInterpolator这个系统的插值 器,那其实系统内置9种插值器的实现,我们通过表格的形式列出来。


image.png

4.自定义插值器

以上我们介绍了插值器的如何使用以及系统内置的9中插值器,其实系统的插值器已经基本可以满足我们平常的开发使用。但是有时候我们需要做到的效果系统的插值器无法实现,我们也可以自定义插值器。

  • 具体实现
    自定义插值器需要实现 Interpolator / TimeInterpolator接口 & 复写getInterpolation()
    (1)补间动画 实现 Interpolator接口;属性动画实现TimeInterpolator接口
    (2)TimeInterpolator接口是属性动画中新增的,用于兼容Interpolator接口,这使得所有过去的Interpolator实现类都可以直接在属性动画使用
  • 实例
    自定义一个Interpolator,先减速后加速
    1、创建MyInterpolator类,实现TimeInterpolator接口,最核心的部分就是通过改变getInterpolation返回值的变化来设置为先减速后加速。
package com.example.administrator.workmanager;

import android.animation.TimeInterpolator;

/**
 * weishixiong
 * 2019/4/23
 */
public class MyInterpolator implements TimeInterpolator {
    @Override
    public float getInterpolation(float input) {
        float result;
        //动画前半部分
        if(input<=0.5){
            result = (float) (Math.sin(Math.PI * input)) / 2;
            // 使用正弦函数来实现先减速后加速的功能,逻辑如下:
            // 因为正弦函数初始弧度变化值非常大,刚好和余弦函数是相反的
            // 随着弧度的增加,正弦函数的变化值也会逐渐变小,这样也就实现了减速的效果。
            // 当弧度大于π/2之后,整个过程相反了过来,现在正弦函数的弧度变化值非常小,
            // 渐渐随着弧度继续增加,变化值越来越大,弧度到π时结束,这样从0过度到π,也就实现了先减速后加速的效果
        }
        else{
            result = (float) (2 - Math.sin(Math.PI * input)) / 2;
        }

        return result;
    }
}

2、给属性动画设置插值器,View执行属性动画

               //获得当前图片的位置
                float curTranslationX = ivOne.getTranslationX();
                // 创建动画对象 & 设置动画
                // 表示的是:
                // 动画作用对象是ivOne
                // 动画作用的对象的属性是X轴平移
                // 动画效果是:从当前位置平移到 x=300 再平移到初始位置
                ObjectAnimator animator = ObjectAnimator.ofFloat(ivOne, "translationX", curTranslationX, 300,curTranslationX);
                animator.setDuration(5000);
                //  // 设置插值器
                animator.setInterpolator(new MyInterpolator());
                // 启动动画
                animator.start();

四、估值器(TypeEvaluator)

1.概念

  • 设置属性值从初始值过度到最终值的具体变化数值。
  • (1)插值器决定的是动画具体的变化规律
  • (2)估值器指的是在某个变化规律上具体的变化数值,比如动画的加速具体的数值。

2、应用场景

配合插值器完成非线性的动画效果

3.具体实现

ObjectAnimator anim = ObjectAnimator.ofObject(myView2, "height", new IntEvaluator(),1,3);

设置一个View的高从1变化到3的效果,在第4个参数中传入对应估值器类的对象,IntEvaluator指的是以整型的形式从初始值 - 结束值 进行过渡。
系统内置的估值器有3个:

  • IntEvaluator:以整型的形式从初始值 - 结束值 进行过渡
  • FloatEvaluator:以浮点型的形式从初始值 - 结束值 进行过渡
  • ArgbEvaluator:以Argb类型的形式从初始值 - 结束值 进行过渡

4.自定义估值器

如果以上系统内置的估值器无法满足开发的需求,我们可以自定义估值器。

  • 实例
    自定义一个估值器,作用在一个圆上,通过改变圆心的坐标,来实现动画效果。
    1、创建圆心实体类Point.java
package com.example.administrator.workmanager;

/**
 * 圆心实体类
 */
public class Point {

    // 设置两个变量用于记录坐标的位置
    private float x;
    private float y;

    // 构造方法用于设置坐标
    public Point(float x, float y) {
        this.x = x;
        this.y = y;
    }

    // get方法用于获取坐标
    public float getX() {
        return x;
    }

    public float getY() {
        return y;
    }
}

2、实现TypeEvaluator接口,自定义估值器

package com.example.administrator.workmanager;

import android.animation.TypeEvaluator;

// 实现TypeEvaluator接口
public class PointEvaluator implements TypeEvaluator {

    /**
     *
     * @param fraction 插值器getInterpolation()的返回值  可以理解为动画进行进度的百分比。
     *                 当进度为100%的时候,即动画完成了
     * @param startValue 动画的初始值
     * @param endValue 动画的结束值
     * @return
     */
    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) {

        // 将动画初始值startValue 和 动画结束值endValue 强制类型转换成Point对象
        Point startPoint = (Point) startValue;
        Point endPoint = (Point) endValue;

        // 根据fraction(动画进行的百分比)来计算当前动画的x和y的值
        float x = startPoint.getX() + fraction * (endPoint.getX() - startPoint.getX());
        float y = startPoint.getY() + fraction * (endPoint.getY() - startPoint.getY());
        
        // 将计算后的坐标封装到一个新的Point对象中并返回
        Point point = new Point(x, y);
        return point;
    }

}

3、将属性动画作用到自定义View当中

package com.example.administrator.workmanager;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

/**
 * weishixiong
 */
public class MyView extends View {
    // 设置需要用到的变量
    public static final float RADIUS = 70f;// 圆的半径 = 70
    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);
    }

    // 复写onDraw()从而实现绘制逻辑
    // 绘制逻辑:先在初始点画圆,通过监听当前坐标值(currentPoint)的变化,每次变化都调用onDraw()重新绘制圆,从而实现圆的平移动画效果
    @Override
    protected void onDraw(Canvas canvas) {
        // 如果当前点坐标为空(即第一次)
        if (currentPoint == null) {
            currentPoint = new Point(RADIUS, RADIUS);
            // 创建一个点对象(坐标是(70,70))

            // 在该点画一个圆:圆心 = (70,70),半径 = 70
            float x = currentPoint.getX();
            float y = currentPoint.getY();
            canvas.drawCircle(x, y, RADIUS, mPaint);


 // (重点关注)将属性动画作用到View中
            // 步骤1:创建初始动画时的对象点  & 结束动画时的对象点
            Point startPoint = new Point(RADIUS, RADIUS);// 初始点为圆心(70,70)
            Point endPoint = new Point(700, 1000);// 结束点为(700,1000)

            // 步骤2:创建动画对象 & 设置初始值 和 结束值
            ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);
            // 参数说明
            // 参数1:TypeEvaluator 类型参数 - 使用自定义的PointEvaluator(实现了TypeEvaluator接口)
            // 参数2:初始动画的对象点
            // 参数3:结束动画的对象点

            // 步骤3:设置动画参数
            anim.setDuration(5000);
            // 设置动画时长

// 步骤3:通过 值 的更新监听器,将改变的对象手动赋值给当前对象
// 此处是将 改变后的坐标值对象 赋给 当前的坐标值对象
            // 设置 值的更新监听器
            // 即每当坐标值(Point对象)更新一次,该方法就会被调用一次
            anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    currentPoint = (Point) animation.getAnimatedValue();
                    // 将每次变化后的坐标值(估值器PointEvaluator中evaluate()返回的Piont对象值)到当前坐标值对象(currentPoint)
                    // 从而更新当前坐标值(currentPoint)

                    // 步骤4:每次赋值后就重新绘制,从而实现动画效果
                    invalidate();
                    // 调用invalidate()后,就会刷新View,即才能看到重新绘制的界面,即onDraw()会被重新调用一次
                    // 所以坐标值每改变一次,就会调用onDraw()一次
                }
            });

            anim.start();
            // 启动动画


        } else {
            // 如果坐标值不为0,则画圆
            // 所以坐标值每改变一次,就会调用onDraw()一次,就会画一次圆,从而实现动画效果

            // 在该点画一个圆:圆心 = (30,30),半径 = 30
            float x = currentPoint.getX();
            float y = currentPoint.getY();
            canvas.drawCircle(x, y, RADIUS, mPaint);
        }
    }


}

4、在布局文件加入自定义View空间

<com.example.administrator.workmanager.MyView
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

已经我们就完成了一个圆,通过自定义估值器,改变圆心坐标,完成圆类似抛物线的效果。

六.总结

属性的动画的实现包含了两个执行类ValueAnimator、ObjectAnimator来执行动画,两个辅助类TypeEvaluator、Interpolator来辅助动画的执行,确定了动画的变化规律和效果。

相关文章

  • 五.属性动画

    一.概念 通过改变对象的属性,完成一系列的动画效果 二.ValueAnimator 1. 概念描述 动画执行类,通...

  • 属性动画学习使用总结

    Android 属性动画总结 属性动画的优点 属性动画的使用步骤 实例化属性动画对象 设置属性动画的时长 启动属性...

  • 动画深入分析(艺术探索读书笔记)

    动画分类:帧动画、View动画、属性动画 View动画 只能作用在View上面的动画,我们平时常用的五个动画类都是...

  • [Android动画]属性动画-小球下落动画实现

    属性动画 属性动画是通过直接改变View属性,实现的动画效果。与补间动画不同的是,属性动画是对象的属性的真实改变,...

  • Android动画-属性动画

    属性动画 所谓属性动画,就是改变对象Object的属性来实现动画过程。属性动画是对View的动画的扩展,通过它可以...

  • 动画之属性动画基础篇

    属性动画 属性动画,改变view或者object的属性实现动画,属性动画比补间动画更强大,不但可以实现旋转、平移等...

  • 【Android 动画】动画详解之属性动画(五)

    在前几篇中,我们了解了补间动画、插值器和属性动画中的ValueAnimator,这一篇,我们来了解下属性动画中的O...

  • UI(四十八)属性动画

    属性动画->通过改变图层或者视图上面的属性值(支持动画的属性)产生的动画 属性动画的常用方法属性: 1、初始化 +...

  • iOS - 属性动画

    属性动画->通过改变图层或者视图上面的属性值(支持动画的属性)产生的动画 属性动画的常用方法属性: 1、初始化+(...

  • Android 动画

    动画类型 视图动画(补间动画、逐帧动画)属性动画 补间动画 逐帧动画 属性动画 对比 插值器:确定属性值从初始值过...

网友评论

    本文标题:五.属性动画

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