Android动画详解(二)

上一篇总结了View动画相关的知识,这一节主要学习Android种的属性动画–也是当前最经常使用的一种动画。它能实现View动画所不能实现的一些动画效果。

1.简介

属性动画(Property Animation)是在 Android 3.0(API 11)后才提供的一种全新动画模式,它大大解决传统动画的局限性,如:经过动画后,其点击事件的响应区域依然未改变。它具有相当高的灵活性,我们可以通过反射机制动态的设置某一个类种的属性从而达到动画的效果。

作用对象:任意Java对象

具体逻辑:此图引用自感谢作者
在这里插入图片描述

其继承结构:
在这里插入图片描述

而我们平常主要使用的是ValueAnimatorObjectAnimator,下面主要介绍它的使用。

2.TypeEvaluator-估值器

如果想要自定义复杂的动画效果,那么我们必须要了解TypeEvaluator。什么是TypeEvaluator呢?
简单来说,就是告诉动画系统如何从初始值过度到结束值。ValueAnimator内部自带FloatEvaluator。我们通过源码可以发现其实现了·TypeEvaluator接口,并且重写了evaluate方法

/**
 * This evaluator can be used to perform type interpolation between <code>float</code> values.
 */
public class FloatEvaluator implements TypeEvaluator<Number> {

    /**
     * This function returns the result of linearly interpolating the start and end values, with
     * <code>fraction</code> representing the proportion between the start and end values. The
     * calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>,
     * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
     * and <code>t</code> is <code>fraction</code>.
     *
     * @param fraction   The fraction from the starting to the ending values
     * @param startValue The start value; should be of type <code>float</code> or
     *                   <code>Float</code>
     * @param endValue   The end value; should be of type <code>float</code> or <code>Float</code>
     * @return A linear interpolation between the start and end values, given the
     *         <code>fraction</code> parameter.
     */
    public Float evaluate(float fraction, Number startValue, Number endValue) {
        float startFloat = startValue.floatValue();
        return startFloat + fraction * (endValue.floatValue() - startFloat);
    }
}
变量含义
fraction表示动画完成度
startValue表示动画开始值
endValue表示动画结束值

3.ValueAnimator的基本使用

看一个简单的Demo,学习基本的使用:

  //ValueAnimator
        //0-2-1之间在5s内重复执行2次,延时一秒开始执行
        //final ValueAnimator animator = ValueAnimator.ofFloat(0f,2f,1f);
        final ValueAnimator animator = ValueAnimator.ofInt(0, 2, 1);
        //动画持续时长
        animator.setDuration(5000);
        //重复次数
        animator.setRepeatCount(2);
        //延迟多久后开始执行
        animator.setStartDelay(1000);
        //动画重复模式,RESTART代表重新播放  REVERSE代表倒序播放
        animator.setRepeatMode(ValueAnimator.RESTART);
        //进度更新的监听
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Log.e("wdl", "onAnimationUpdate: " + (int) animation.getAnimatedValue());
            }
        });

基本的方法有:
在这里插入图片描述

3.ObjectAnimator的基本使用

ObjectAnimator.ofXxx(Object target,String propertyName,Args...value),第一个参数代表目标对象,第二个参数为想要操作的属性名,最后一个为一个可变长参数。

 //独立动画效果
        //透明度
        final ObjectAnimator alphaObjectAnimator = ObjectAnimator
                .ofFloat(imageView,"alpha",1f,0f,1f);
        //旋转
        final ObjectAnimator rotateObjectAnimator = ObjectAnimator
                .ofFloat(imageView,"rotation",0f,360f);
        //缩放
        final ObjectAnimator scaleXObjectAnimator = ObjectAnimator
                .ofFloat(imageView,"scaleX",1f,2f,1f);
        final ObjectAnimator scaleYObjectAnimator = ObjectAnimator
                .ofFloat(imageView,"scaleY",1f,2f,1f);
        float translateY = imageView.getTranslationY();
        Log.e("wdl", "translateY: "+translateY);
        final ObjectAnimator translateYObjectAnimator = ObjectAnimator.
                ofFloat(imageView,"translationY",
                translateY,-600f,translateY);

//        alphaObjectAnimator.setDuration(5000);
//        rotateObjectAnimator.setDuration(5000);
//        scaleXObjectAnimator.setDuration(5000);
//        scaleYObjectAnimator.setDuration(5000);
//        translateYObjectAnimator.setDuration(5000);

        //FloatEvaluator
        //组合动画
        final AnimatorSet animatorSet = new AnimatorSet();
        //play方法返回一个Builder对象
        //树结构
        //after 就是在当前的基础上添加一个父亲节点 ,只能添加一个父亲节点(子节点只能有一个父亲节点)
        //before 在当前基础上添加孩子节点,可以添加2个子节点
        animatorSet.play(translateYObjectAnimator).with(alphaObjectAnimator)
                .after(rotateObjectAnimator)
                .before(scaleXObjectAnimator).before(scaleYObjectAnimator);
        animatorSet.setDuration(5000);
        //添加所有的监听
        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) {

            }
        });
        //根据需求重写监听方法
        animatorSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
            }

            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
            }
        });

其中AnimatorSet,组合动画有四个方法:

//play方法返回一个Builder对象
        //树结构
        //after 就是在当前的基础上添加一个父亲节点 ,只能添加一个父亲节点(子节点只能有一个父亲节点)
        //before 在当前基础上添加孩子节点,可以添加2个子节点
        animatorSet.play(translateYObjectAnimator).with(alphaObjectAnimator)
                .after(rotateObjectAnimator)
                .before(scaleXObjectAnimator).before(scaleYObjectAnimator);
        animatorSet.setDuration(5000);

查看相关源码:

 /**
         * Sets up the given animation to play when the animation supplied in the
         * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object
         * ends.
         *
         * @param anim The animation that will play when the animation supplied to the
         * {@link AnimatorSet#play(Animator)} method ends.
         */
        public Builder before(Animator anim) {
            Node node = getNodeForAnimation(anim);
            mCurrentNode.addChild(node);
            return this;
        }

        /**
         * Sets up the given animation to play when the animation supplied in the
         * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object
         * to start when the animation supplied in this method call ends.
         *
         * @param anim The animation whose end will cause the animation supplied to the
         * {@link AnimatorSet#play(Animator)} method to play.
         */
        public Builder after(Animator anim) {
            Node node = getNodeForAnimation(anim);
            mCurrentNode.addParent(node);
            return this;
        }

可以看出,使用的是树结构:

方法作用
play方法返回一个Builder对象
with与play种的动画一起执行
after就是在当前的基础上添加一个父亲节点 ,只能添加一个父亲节点(子节点只能有一个父亲节点),此动画在前面的动画之前执行
before在当前基础上添加孩子节点,可以添加2个子节点,在前面的动画之后执行

4.总结一下常用的方法

方法作用
setDuration动画持续时长
setRepeatCount动画重复次数
setStartDelay动画延时开始的时长
setRepeatMode动画重复模式
addUpdateListener动画监听

5.XML中使用

动画相关文件位于res/animator/下。

基本使用:(基本的属性作用与Java代码中的类似)

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially">
    <!--   android:ordering    sequentially按照xml文件中的先后顺序执行    together同时执行 -->
    <objectAnimator
        android:duration="2000"
        android:propertyName="translationX"
        android:valueFrom="-500"
        android:valueTo="0"
        android:valueType="floatType" />

    <set android:ordering="together">
        <objectAnimator
            android:duration="3000"
            android:propertyName="rotation"
            android:valueFrom="0"
            android:valueTo="360"
            android:valueType="floatType" />
        <set android:ordering="sequentially">
            <objectAnimator
                android:duration="1500"
                android:propertyName="alpha"
                android:valueFrom="1"
                android:valueTo="0"
                android:valueType="floatType" />
            <objectAnimator
                android:duration="1500"
                android:propertyName="alpha"
                android:valueFrom="0"
                android:valueTo="1"
                android:valueType="floatType" />
        </set>
    </set>
</set>

Java中使用:

 Animator xmlAnimator = AnimatorInflater.loadAnimator(this,R.animator.animations);
 //将动画设置给对应的view
xmlAnimator.setTarget(imageView);
xmlAnimator.start();

本文参考:
https://blog.csdn.net/guolin_blog/article/details/43816093
https://www.jianshu.com/p/2412d00a0ce4
https://blog.csdn.net/guolin_blog/article/details/43536355
https://blog.csdn.net/guolin_blog/article/details/43816093

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值