zoukankan      html  css  js  c++  java
  • Android动画效果之初识Property Animation(属性动画)

    前言:

         前面两篇介绍了Android的Tween Animation(补间动画) Android动画效果之Tween Animation(补间动画)、Frame Animation(逐帧动画)Android动画效果之Frame Animation(逐帧动画)(二),其实总结前两个的根本目的就是为了学习今天的主角Property Animation(属性动画)。其实在Android最早期只提供了前两种动画方式,在Android 3.0才引入了属性动画,谷歌为何要引入属性动画呢?今天我们来总结学习一下。

         其他几种动画效果:

    Property Animation产生的背景:

        由于Tween Animation(补间动画)只能实现简单的四种的动画(alpha、scale、rotate、translate),要想实现比较复杂的动画就难以满足需求,而且补间动画只是改变了View对象绘制的位置,而没有改变View对象本身,比如View形状的变换,如大小的缩放,透明度的改变,位置的改变,其实本身并没有改变,举个例子就好比孙悟空灵魂出窍一样,虽然已经上天入地,其实肉体还在那里一动不动,我们开发过程中的经常遇见的就是translate之后事件还在原地。如果要实现既要有动画效果又要使得View本身得到真正改变,那就要借助属性动画了,这也是属性动画引入的原因。它能够更加灵活的实现各种效果,不仅限于类似补间动画实现的哪几种效果。

    Property Animation相关类

       属性动画,根据字面理解可以通过修改物件的属性值以达到动画效果。

    类名 用途
    ValueAnimator 属性动画主要的计时器,也计算动画后的属性的值,动画的执行类
    ObjectAnimator   ValueAnimator的一个子类,允许你设置一个目标对象和对象的属性进行动画,动画的执行类
    AnimatorSet 提供组织动画的结构,使它们能相关联得运行,用于控制一组动画的执行
    AnimatorInflater  用户加载属性动画的xml文件
    Evaluators  属性动画计算器,告诉了属性动画系统如何计算给出属性的值
    Interpolators 动画插入器,定义动画的变化率

     上面几个重要类之间的关系如下图所示:

    今天先通过最简单最容易理解的ObjectAnimator来学习总结。

    ObjectAnimator:

       ValueAnimator的一个子类,允许你设置一个目标对象和对象的属性进行动画。当这个类计算好一个动画的新值后,相应的会更新其属性。大多数时候你都会想用ObjectAnimator,因为它使得动画值到目标对象的处理更简单了。

    1.)以实现一个View透明渐变效果为例进行说明

    xml实现方式:

    这里需要注意是的属性动画文件存放目录为res/animator

    <?xml version="1.0" encoding="utf-8"?>
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="500"
        android:propertyName="alpha"
        android:repeatCount="1"
        android:repeatMode="reverse"
        android:startOffset="200"
        android:valueFrom="0.0"
        android:valueTo="1.0"
        android:valueType="floatType" />

    duration 表示动画执行的时间

    propertyName 表示修改的物件的哪个属性值,这里是透明度

    valueFrom 表示从哪个状态值开始动画

    valueTo 表示到哪个状态值结束动画

    valueType 类型估值,主要用于设置动画操作属性的值

    repeatMode 表示重复的模式 reverse表示

    repeatCount 动画重复的计数,动画将会执行该值+1次

    repeatMode 动画重复的模式,reverse为反向,当第偶次执行时,动画方向会相反。restart为重新执行,方向不变

    startOffset, 动画多次执行的间隔时间,如果只执行一次,执行前会暂停这段时间,单位毫秒 

    interpolator 指定动画插入器

    通过上面的xml属性可以看出和补间动画基本上一致,然后通过AnimatorInflater 来加载xml中的动画

    Animator anim = AnimatorInflater.loadAnimator(this, R.animator.animator_alpha);
    anim.setTarget(imageView);
    anim.start();

    当然也可以通过纯Java代码的方式实现

    ObjectAnimator alphaAnimation = ObjectAnimator.ofFloat(imageView, "alpha", 0f, 1f);
        alphaAnimation.setDuration(500);
        alphaAnimation.setRepeatCount(0);
        alphaAnimation.setRepeatMode(ValueAnimator.REVERSE);
        alphaAnimation.setStartDelay(200);
        alphaAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
        alphaAnimation.start();

    对于java代码实现,ObjectAnimator 提供了以下几个方法:ofFloat(),ofInt(),ofObject(),ofArgb(),ofPropertyValuesHolder()这几个方法都是设置动画作用的元素、作用的属性、动画开始、结束、以及中间的任意个属性值。

    其他举例:

    缩放动画:

    xml:

    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
      android:duration="500"
      android:propertyName="scaleX"
      android:repeatCount="1"
      android:repeatMode="reverse"
      android:valueFrom="1.0"
      android:valueTo="1.5"
      android:valueType="floatType" />

    java代码:

     ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(imageView, "scaleX", 1f, 1.5f);
       scaleXAnimator.setDuration(500);
       scaleXAnimator.setRepeatCount(1);
       scaleXAnimator.setRepeatMode(ValueAnimator.REVERSE);
       scaleXAnimator.start();
    旋转动画:

     xml:

    <?xml version="1.0" encoding="utf-8"?>
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="500"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:propertyName="rotation"
        android:repeatCount="1"
        android:repeatMode="reverse"
        android:valueFrom="0"
        android:valueTo="360"
        android:valueType="floatType" />

    java代码:

     ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 360f);
        objectAnimator.setDuration(500);
        objectAnimator.setRepeatCount(1);
        objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
        objectAnimator.start();
    平移动画:

    xml:

    <?xml version="1.0" encoding="utf-8"?>
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="500"
        android:propertyName="translationX"
        android:repeatCount="1"
        android:repeatMode="reverse"
        android:valueFrom="0"
        android:valueTo="100"
        android:valueType="floatType" />

    java代码:

     ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "translationX", 0f, 100f);
        objectAnimator.setDuration(500);
        objectAnimator.setRepeatCount(1);
        objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
        objectAnimator.start();

    2.)如何实现一个组合动画

        举例我们同时对一个控件进行宽高两个维度的缩放

      方式一:使用AnimatorSet
    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android"
        android:ordering="together">
        <objectAnimator
            android:duration="500"
            android:propertyName="scaleX"
            android:repeatCount="1"
            android:repeatMode="reverse"
            android:valueFrom="1.0"
            android:valueTo="1.5"
            android:valueType="floatType" />
        <objectAnimator
            android:duration="500"
            android:propertyName="scaleY"
            android:repeatCount="1"
            android:repeatMode="reverse"
            android:valueFrom="1.0"
            android:valueTo="1.5"
            android:valueType="floatType" />
    
    </set>

    加载xml动画

        Animator anim = AnimatorInflater.loadAnimator(this, R.animator.animator_scale);
          anim.setTarget(imageView);
          anim.start();

    纯Java代码实现:

    AnimatorSet animatorSet = new AnimatorSet();
    
        ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(imageView, "scaleX", 1f, 1.5f);
        scaleXAnimator.setDuration(500);
        scaleXAnimator.setRepeatCount(1);
        scaleXAnimator.setRepeatMode(ValueAnimator.REVERSE);
        scaleXAnimator.start();
    
        ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(imageView, "scaleY", 1f, 1.5f);
        scaleYAnimator.setDuration(500);
        scaleYAnimator.setRepeatCount(1);
        scaleYAnimator.setRepeatMode(ValueAnimator.REVERSE);
    
        animatorSet.playTogether(scaleXAnimator, scaleYAnimator);
        animatorSet.start();

    上述代码通过playTogether函数实现两个动画同时执行,如果不想同时执行,也可以调用play函数返回AnimatorSet.Builder实例,AnimatorSet.Builder提供了如下几个函数用于实现动画组合:

    1. after(Animator anim) 将现有动画插入到传入的动画之后执行
    2. after(long delay) 将现有动画延迟指定毫秒后执行
    3. before(Animator anim) 将现有动画插入到传入的动画之前执行
    4. with(Animator anim) 将现有动画和传入的动画同时执行

    也可以调用playSequentially函数实现分布执行动画。

      方式二:使用PropertyValuesHolder
    PropertyValuesHolder scaleXValuesHolder = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 1.5f);
    PropertyValuesHolder scaleYValuesHolder = PropertyValuesHolder.ofFloat("scaleY", 1.0f, 1.5f);
    ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(imageView, scaleXValuesHolder, scaleYValuesHolder);
        objectAnimator.setDuration(500);
        objectAnimator.setRepeatCount(1);
        objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
        objectAnimator.start();

    通过这种方式只能实现同时执行的动画组合相比AnimatorSet就没那么丰富了,PropertyValuesHolder 提供的函数方法有如下几种:ofInt()、ofFloat()、ofObject()、ofKeyframe()。

    方式三:使用ViewPropertyAnimator
     ViewPropertyAnimator viewPropertyAnimator=imageView.animate();
     viewPropertyAnimator.scaleXBy(1.0f).scaleX(1.5f).scaleYBy(1.0f).scaleY(1.5f).setDuration(500).start();

    多属性动画,作用于View,能够实现的动画相对单一,只能实现比如缩放,透明度改变,平移、旋转等,具体函数名字:平移 translationX,translationY, X,Y,缩放 scaleX,scaleY, 旋转 rotationX, rotationY,透明度 alpha

    3.)设置动画监听器

    有时候我们可能要在某一个动画执行之前 或者动画结束之后进行一些其他的操作,这个时候就要借助动画监听器了。

        objectAnimator.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {
            //TODO 动画开始前的操作
        }
    
        @Override
        public void onAnimationEnd(Animator animation) {
            //TODO 动画结束的操作
        }
    
        @Override
        public void onAnimationCancel(Animator animation) {
           //TODO 动画取消的操作
        }
    
        @Override
        public void onAnimationRepeat(Animator animation) {
            //TODO 动画重复的操作
        }
        });

    如果我们需要简单动画执行过程中的变化可以使用AnimatorUpdateListener

     objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            float value = (float) animation.getAnimatedValue();
            //可以根据自己的需要来获取动画更新值。
            Log.e("AnimatorUpdateListener", "the animation value is " + value);
        }
        });

    总结:

       本篇主要先简单认识一下属性动画,以及利用属性动画实现补间动画。后续会对属性动画进行进一步的学习。

  • 相关阅读:
    git 强制覆盖本地
    .gitignore 配置
    Git fetch和git pull的区别
    时间函数 date strtotime
    page show
    prepare PDO
    Lucene搜索方法总结
    lucene索引日期和数字
    lucene 3.0.2 + 多文件夹微博数据(时间,微博)构建索引
    lucene 使用注意
  • 原文地址:https://www.cnblogs.com/whoislcj/p/5738478.html
Copyright © 2011-2022 走看看