Android动画-Property Animation(一)

本章内容

在之前 《Android动画-概述》中,我大概说了下Android Property Animation的由来,这里就不做多介绍了,Property Animation 肯定不是一章就能讲的完的,接下来的几章都是建立在代码、效果图的基础上,介绍Property Animation的用法。
本章主要讲的是 ObjectAnimator ,包括代码生成动画,XML加载动画。


简述:在给出一大堆代码之前,先通过效果图来看看一些有趣的动画,通过一个简单有趣的动画逐步展开:

这里写图片描述

这绝对是一个非常有趣的动画,包含了 alpha、translationX、translationY、rotationX、rotationY、scaleX、scaleY , 一堆 Animation 名词,在详细看这个效果的代码之前,先了解一些重要的东西,有个印象就行,毕竟之后会很详细的说明,担心后面大家看的一头雾水:

View Animation 和 Property Animation

alpha 依然不变

translate 分成了 translationX 和 translationY, 要想X轴、Y轴两个一起变化就需要将 translationX 和 translationY 组合使用

rotate 分成了 rotation、rotationX、 rotationY,其中 rotation 和 rotate基本一致,都是围绕某一个中心旋转,而 rotationX 和 rotationY 则应该算 Property Animation 带来的新的效果,这两种动画分别表示着 X轴的立体动画和Y轴的立体动画。

scale 则分成了 scaleX 和 scaleY,和 translationX/Y 一样,要想X轴、Y轴都有变化就必须一起使用

共同点:
duration 动画时间
repeatCount 动画重复次数
repeatMode 动画重复模式
Interpolator 插值器

接下来,还需要看看3.0之后,View的变化

aplha:透明度,1是完全不透明,0是完全透明,这个也没什么好说的。

setTranslationX(floatX)、setTranslationY(floatY) 这两个API的作用是对控件的位置进行调整,floatX 和 floatY 是一个相对值,相对于控件左上角原点的一个位移值。

setRotationX(floatX) 和 setRotationY(floatY) ,这两个API分别代表着 改变与X轴平面的角度、改变与Y轴平面的角度,这话说的非常抽象,事实上这两个API的效果也非常抽象,举个栗子:把X轴、Y轴看成两个垂直的平面,现在有一个ImageView 在画面上,这个ImageView 现在肯定是与Y轴的平面平行,与X轴的平面垂直,如果我设置了 setRotationX(45),这个45代表的就是一个正45度角,那么这个ImageView 就会变成一个底部向屏幕内延伸,倾斜的角度与X轴平面的角度成45度角,小角对着你。(感觉说完还是很抽象,下面会有效果,一会儿大家看看吧,事实上开发中,我基本没有用到过,好奇葩的API)

setScaleX(floatX) 、setScaleY(floatY) 这个就简单了,代表着 X轴方向的缩放,Y轴方向的缩放

setPivotX(floatX) 和 setPivotY(floatY):旋转的轴点和缩放的基准点,默认是View的中心点。和View Animation 不一样,Property Animation 提供的API和XML这两种创建动画的途径中,都没有额外的位置设置中心点,所以不管是 代码还是加载XML ,最后的中心点都是动画控件本身在代码里面去设置的。

setX(floatX) set(floatY) : 这个API是设置控件在屏幕上的绝对位置,这里 floatX 和 floatY都是 绝对坐标点


看完新的API,先贴一下上面那个 Set 动画的代码,仅仅只是看上去,很多代码,其实就是一个方法:

public void set1(View view) {
        AnimatorSet set = new AnimatorSet();
        set.setDuration(3000);
        set.playTogether(
                ObjectAnimator.ofFloat(imageView, "alpha", 0.3f, 1f),
                ObjectAnimator.ofFloat(imageView, "scaleY", 0.1f, 1f),
                ObjectAnimator.ofFloat(imageView, "scaleX", 0.1f, 1f),
                ObjectAnimator.ofFloat(imageView, "rotationX", 0f, 360f),
                ObjectAnimator.ofFloat(imageView, "rotationY", 0f, 360f),
                ObjectAnimator.ofFloat(imageView, "translationY", 0f, -400f, 0f),
                ObjectAnimator.ofFloat(imageView, "translationX", 0f, -400f, 0f));
        set.start();
    }

AnimatorSet 作为 Property Animation 中的动画集合,提供了多种动画API,这里用了

public void playTogether(Animator... items)

从方法名就可以看出这是一个一起动画的API,参数是可变数组,类型是 Animator,这是一个抽象类,所以我们要使用它的子类,ObjectAnimator的父类是ValueAnimator(Property Animation核心类,本章先不介绍它),ValueAnimator继承于Animator,在 Property Animation 中做一些简单的动画,我一般都是用ObjectAnimator。
普通动画APIpublic static ObjectAnimator ofFloat(Object target, String propertyName, float... values),tartget 毫无疑问是动画控件,propertyName从上面的代码中可以看出,这个给定了你要制定的动画类型,最后一个参数是一个可变数组。这里就可以看出Property Animation对于普通动画,它需要的只是结果,也即是也想要这个动画经历什么值,直接告诉API,然后其中实现、过渡这些都是不需要管的。


Alpha

这个是用代码实现的:

这里写图片描述

public void alpha(View view) {
        ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "alpha", 1f,
                0.1f, 1f, 0.5f, 1f);
        anim.setDuration(5000);
        anim.start();
    }

这是一个最基本的透明渐变的动画,我希望我的ImageView在5秒内的透明度 1f-0.1f-1f-0.5f-1f,然后接下来就和我没有关系了。

接下来,让我们来XML定义一个动画,xml 定义路径:res/animator

这里写图片描述

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially">

    <objectAnimator
        android:duration="1400"
        android:propertyName="alpha"
        android:valueFrom="0.3"
        android:valueTo="1"
        android:valueType="floatType" />

    <objectAnimator
        android:duration="2000"
        android:propertyName="alpha"
        android:valueFrom="1"
        android:valueTo="0.1"
        android:valueType="floatType" />

    <objectAnimator
        android:duration="1400"
        android:propertyName="alpha"
        android:valueFrom="0.1"
        android:valueTo="0.8"
        android:valueType="floatType" />

</set>

很明显一个objectAnimator节点是无法承载多个动画的,必须使用set,在set下还需要指明它的子节点动画是一起执行,还是按照XML顺序依次执行。这里android:ordering="sequentially"我规定是按照顺序依次执行。还有一个值,规定一起执行的:android:ordering="together"
XML中 定义:第一,执行动画的类型 android:propertyName,和 View Animation不一样,View Animation 中一种动画会有对应的节点,而Property Animation中所有基本动画的节点都是objectAnimator,区别动画的类型则是一个属性:android:propertyName。比如 alpha :android:propertyName=”alpha”。第二,在Property Animation的XML中只有android:valueFrom=”0.1” 和 android:valueTo=”0.8” 这两个动画值得存在,不存在规定 scale动画基点的属性,以及规定 rotation 中心的属性,这些都得去到java中调用对应控件的API去设置才成:setPivotX(floatX) 和 setPivotY(floatY)。
动态加载XML:

public void alpha(View view) {
//        Animator animator = AnimatorInflater.loadAnimator(this, R.animator.base_alpha_animator); // 简单的透明动画
        Animator animator = AnimatorInflater.loadAnimator(this, R.animator.base_set_alpha); // 复杂的透明动画
        animator.setTarget(imageView);
        animator.start();
    }

这里AnimatorInflater,就是一个用于动态加载的类。

scale

代码动画:

这里写图片描述

public void scale(View view) {
        ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "scaleX", 0.1f, 1f, 0.3f, 0.7f, 0.5f);
        imageView.setScaleY(2);
//        imageView.setScaleX(2);
        anim.setDuration(3000);
        anim.setRepeatCount(1);
        anim.setRepeatMode(ObjectAnimator.REVERSE);
        anim.start();
    }

这里设置了repeatCount和repaeatMode给大家看看效果,顺便测试了了一个View.setScaleY,效果很明显 动画顺序反着又播了一遍,并且控件高度变成2倍。

XML

这里写图片描述

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:ordering="together">

    <set android:ordering="sequentially">
        <objectAnimator
            android:propertyName="scaleX"
            android:valueFrom="1"
            android:valueTo="1.5"
            android:valueType="floatType" />

        <objectAnimator
            android:propertyName="scaleX"
            android:valueFrom="1.5"
            android:valueTo="0.1"
            android:valueType="floatType" />
    </set>

    <set android:ordering="sequentially">
        <objectAnimator
            android:propertyName="scaleY"
            android:valueFrom="1"
            android:valueTo="0.1"
            android:valueType="floatType" />

        <objectAnimator
            android:propertyName="scaleY"
            android:valueFrom="0.1"
            android:valueTo="1.5"
            android:valueType="floatType" />
    </set>

</set>

正如之前说的,在Property Animation中如果想要X轴、Y轴一起变化,就需要同时使用scaleX、scaleY,在这个XML中我得想法是 把X轴的变化作为一个set,Y轴的变化是另一个set,它们的运行规定是依次运行,之后再把这两个set一起运行。也就是 together下包含着两个sequentially。其实另一种写法可以是sequentially包含着两个together,就是把某一阶段X/Y轴的变化看成是一体的,然后一阶段一阶段的进行。

rotation

先看个最简单的平面动画

这里写图片描述

 public void rotate(View view) {
//        ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "rotationY", 0f, 360f, 200f, 315f, 225f, 269f);  这是个逗逼的动画
        ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 720f);
//        imageView.setRotationX(-45);
//        imageView.setRotationY(-30);
        imageView.setPivotX(-100f);
        imageView.setPivotY(-100f);
        anim.setDuration(5000);
        anim.setInterpolator(new AccelerateInterpolator());
        anim.start();
    }

这是一个非常简单的动画,其实就是在模拟View Animation 中的rotate,这里如果不设置imageView.setPivotX(-100f); imageView.setPivotY(-100f);那么它的默认旋转中心就是ImageView本身的中心点,需要说的是,这里的imageView.setPivotX(-100f);
imageView.setPivotY(-100f)都是相对于控件左上角的相对位置;并且这里使用了 加速 的插值器。

3D动画

这里写图片描述

    public void rotate(View view) {
//        ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "rotationY", 0f, 360f, 200f, 315f, 225f, 269f);  这是个逗逼的动画
        ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "rotationY", 0f, 720f);
//        imageView.setRotationX(-45);
//        imageView.setRotationY(-30);
        imageView.setPivotX(-100f);
        imageView.setPivotY(-100f);
        anim.setDuration(5000);
        anim.setInterpolator(new AccelerateInterpolator());
        anim.start();
    }

rotationY就是围绕中心点做的Y轴方向的3D动画,如果你想看X轴方向,换成rotationX就OK了。

倾斜旋转动画

这里写图片描述

    public void rotate(View view) {
//        ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "rotationY", 0f, 360f, 200f, 315f, 225f, 269f);  这是个逗逼的动画
        ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 720f);
        imageView.setRotationX(-45);
//        imageView.setRotationY(-30);
//        imageView.setPivotX(-100f);
//        imageView.setPivotY(-100f);
        anim.setDuration(5000);
        anim.setInterpolator(new AccelerateInterpolator());
        anim.start();
    }

imageView.setRotationX(-45) 这个API表示着,ImageView底部向屏幕内侧倾斜45°,也就是ImageVIew和X轴平面的相交,角度从90°,变成45°,就变成上图中的效果。

XML

这里写图片描述

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially">

    <objectAnimator
        android:duration="1500"
        android:propertyName="rotation"
        android:valueFrom="0"
        android:valueTo="28"
        android:valueType="floatType" />


    <objectAnimator
        android:duration="1500"
        android:propertyName="rotationX"
        android:valueFrom="0"
        android:valueTo="360"
        android:valueType="floatType" />

</set>
   public void rotate(View view) {
//        Animator animator = AnimatorInflater.loadAnimator(this, R.animator.base_rotation_animator); //简单的旋转动画
        Animator animator = AnimatorInflater.loadAnimator(this, R.animator.base_set_rotate);
        animator.setTarget(imageView);
        imageView.setPivotX(imageView_height);
        imageView.setPivotY(0);
        animator.start();
    }

这个旋转动画是先正方向旋转28°,将对角线与X轴平行,然后在代码里面将对角线上的点作为中心点旋转,其实也就是绕着对角线旋转

translation

这里写图片描述

public void translate(View view) {
        imageView.setTranslationX(-200);
        ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "translationY", 0f, -400f, 0f);
        anim.setDuration(3000);
        anim.start();
    }

以控件左上角为原点位移-200px imageView.setTranslationX(-200),然后translationY,从0位移-400,最后在回到Y轴的原点。


XML

这里写图片描述

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:ordering="together">

    <set android:ordering="sequentially">

        <objectAnimator
            android:propertyName="translationX"
            android:valueFrom="-150"
            android:valueTo="0" />

    </set>

    <set android:ordering="sequentially">

        <objectAnimator
            android:propertyName="translationY"
            android:valueFrom="-200"
            android:valueTo="0" />

        <objectAnimator
            android:interpolator="@android:anim/bounce_interpolator"
            android:propertyName="translationY"
            android:valueFrom="0"
            android:valueTo="100" />

    </set>

</set>

回弹的效果看不到也是没辙。

抛物线

这里写图片描述

private float setX = 0;

    public void setXY(View view) {
        imageView.setScaleX(0.1f);
        imageView.setScaleY(0.1f);
        setX = 0;
        ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "cjh", 0f, 1f);
        anim.setDuration(3000);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (Float) animation.getAnimatedValue();//得到动画变化的属性值
                setX = 400 * value;
                float setY = -1 / 75 * setX * setX + 4 * setX;
                imageView.setX(setX);
                imageView.setY(setY);
            }
        });
        anim.start();
    }

事实上,Property Animation 是可以拿到时间值然后自定义动画效果,代码中,我定义我要从 0 - 1,但是具体做什么我随便写的,然后在刷新监听里面,调用了抛物线的公式,然后 setX setY,不断更新ImageView的位置


至此,关于 Proerty Animation 的基本使用都讲完了,主要是详细的讲了 ObjectAnimator 的使用和XML的写法,接下来就是更为重要的动画了。

源码下载

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值