美文网首页
Android 动画 | 艺术探索笔记

Android 动画 | 艺术探索笔记

作者: brickx | 来源:发表于2018-11-05 21:35 被阅读0次

    Android 动画分为两大类

    • 视图动画
    • 属性动画

    视图动画(View animation)

    视图动画分为

    • 补间动画
    • 帧动画

    补间动画(Tween animation)

    补间动画有四类

    名称 XML 标签 子类 效果
    平移动画 <translate> TranslateAnimation 移动 View
    缩放动画 <scale> ScaleAnimation 缩放 View
    旋转动画 <rotate> RotateAnimation 旋转 View
    透明度动画 <alpha> AlphaAnimation 改变 View 透明度

    在 XML 中使用补间动画

    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@[package:]anim/interpolator_resource"
        android:shareInterpolator=["true" | "false"] >
        <alpha
            android:fromAlpha="float"
            android:toAlpha="float" />
        <scale
            android:fromXScale="float"
            android:toXScale="float"
            android:fromYScale="float"
            android:toYScale="float"
            android:pivotX="float"
            android:pivotY="float" />
        <translate
            android:fromXDelta="float"
            android:toXDelta="float"
            android:fromYDelta="float"
            android:toYDelta="float" />
        <rotate
            android:fromDegrees="float"
            android:toDegrees="float"
            android:pivotX="float"
            android:pivotY="float" />
        <set>
            ...
        </set>
    </set>
    

    <set>标签表示动画集合,在它内部可以包含多个补间动画,它存在两个属性

    • android:interpolator
    • android:shareInterpolator

    android:interpolator表示该动画集合的插值器。Android 中内置了九种插值器供我们选择,默认为accelerate_decelerate_interpolator,即先加速后减速。

    内置的九种插值器

    android:shareInterpolator表示集合中的动画和集合是否共用一个插值器。

    <alpha>标签表示透明度动画,它的属性有

    • android:fromAlpha:透明度的起始值
    • android:toAlpha:透明度的结束值

    <scale>标签表示缩放动画,它的属性有

    • android:fromXScale:水平方向缩放的起始值
    • android:toXScale:水平方向缩放的结束值
    • android:fromYScale:竖直方向缩放的起始值
    • android:toYScale:竖直方向缩放的结束值
    • android:pivotX:缩放轴点的 x 坐标
    • android:pivotY:缩放轴点的 y 坐标

    默认情况下,轴点为 View 的中心点。轴点为中心点意味着,会从左右两边同时缩放。如果轴点为右边界,那么 View 就只会从左边缩放。

    <translate>标签表示平移动画,它的属性有

    • android:fromXDelta:x 的起始值
    • android:toXDelta:x 的结束值
    • android:fromYDelta:y 的起始值
    • android:toYDelta:y 的结束值

    <rotate>标签表示旋转动画,它的属性有

    • android:fromDegrees:旋转开始角度
    • android:toDegrees:旋转结束角度
    • android:pivotX:旋转轴点的 x 坐标
    • android:pivotY:旋转轴点的 y 坐标

    轴点即为旋转轴,默认情况为 View 的中心点。

    除此之外,补间动画还有一些通用的属性

    • android:duration:动画持续时间
    • android:fillAfter:动画结束后是否停留在结束位置,true 为停留,false 不停留

    定义一个动画

    // res/anim/animation.xml
    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android"
        android:fillAfter="true"
        android:zAdjustment-"normal" >
    
        <rotate
            android:duration="100"
            android:fromDegrees="0"
            android:toDegrees="90" />
    </set>
    

    使用该动画

    Button b = (Button) findViewById(R.id.button);
    Animation animation = AnimationUtils.loadAnimation(this, R.anim.animation);
    b.startAnimation(animation);
    

    帧动画(Frame animation)

    帧动画的使用

    // res/drawable/frame_animation.xml
    <?xml version="1.0" encoding="utf-8"?>
    <animation-list xmlns:android="http://schemas.android.com/apk/res/android"
        android:oneshot="false" >
    
        <item android:drawable="@drawable/image1" android:duration="1000" />
        <item android:drawable="@drawable/image1" android:duration="1000" />
        <item android:drawable="@drawable/image1" android:duration="1000" />
    </animation-list>
    

    android:oneshot表示是否只播放一次,默认为 false。

    使用帧动画

    Button b = (Button) findViewById(R.id.button);
    b.setBackgroundResource(R.drawable.frame_animation);
    AnimationDrawable d = (AnimationDrawable) b.getBackground();
    d.start();
    

    帧动画时应避免使用多张大图,否则容易引起内存溢出。

    属性动画(Property animation)

    属性动画于 Android 3.0(API 11)引入。与视图动画(View animation)不同的是,属性动画可以对任意象做动画,也包括没有对象的情况。与视图动画不同的是,属性动画会真正的改变对象的属性。

    属性动画的工作流程

    1. 设置动画运行时长、动画效果以及初始值和结束值
    2. 通过插值器和估值器设置属性的变化逻辑
    3. 根据步骤二的变化逻辑不断改变值
    4. 根据值的改变给对象赋值
    5. 调用 invalidate 方法绘制视图
    6. 重复步骤四和步骤五,直到初始值等于结束值
    属性动画工作流程

    属性动画常用类

    • ObjectAnimator
    • AnimatorSet
    • ValueAnimator

    ValueAnimator

    ValueAnimator 获取变化后的值,手动将值赋给对象的属性,从而实现动画效果。

    ValueAnimator 流程

    ValueAnimator.ofInt、ValueAnimator.ofFloat、ValueAnimator.ofObject 方法分别会以整型、浮点型、对象的方式将初始值过度到结束值。在这三个方法中需要传入动画的初始值、中间值(可以不传入)和结束值,在使用 ValueAnimator 时需要添加监听,以便得到执行过程中每一个动画值。

    通过 Java 代码实现动画

    ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 5);
    valueAnimator.setDuration(1000);
    valueAnimator.start();
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            // 获得变化后的属性值
            float currentValue = (float) animation.getAnimatedValue();
            Log.d("ValueAnimator", "动画值:" + currentValue);
            // 手动设置属性值
            button.getLayoutParams().width = currentValue;
            // 刷新视图
            button.requestLayout();
        }
    });
    

    ObjectAnimator

    ObjectAnimator 获取变化后的值,通过 get 和 set 方法自动将值赋给对象的属性,从而实现动画效果。

    ObjectAnimator 流程

    ObjectAnimator 继承自 ValueObject,所以同样有 ObjectAnimator.ofInt、ObjectAnimator.ofFloat、ObjectAnimation.ofObject 方法,作用与 ValueAnimator 类似。

    通过 Java 代码实现动画

    ObjectAnimator.ofFloat(button, "translationX", 0, 100).setDuration(1000).start();
    

    AnimatorSet

    通过 Java 代码实现动画

    AnimationSet set = new Animation();
    set.playTogether(
        ObjectAnimator.ofFloat(imag, "translationX", 0, 100),
        ObjectAnimator.ofFloat(imag, "translationY", 0, 100),
        ObjectAnimator.ofFloat(imag, "rotationX", 0, 360)
    );
    set.setDuration(3000).start();
    

    通过 XML 定义动画

    // res/animator/property_animator.xml
    <set
      android:ordering=["together" | "sequentially"]>
    
        <objectAnimator
            android:propertyName="string"
            android:duration="int"
            android:valueFrom="float | int | color"
            android:valueTo="float | int | color"
            android:startOffset="int"
            android:repeatCount="int"
            android:repeatMode=["repeat" | "reverse"]
            android:valueType=["intType" | "floatType"]/>
    
        <animator
            android:duration="int"
            android:valueFrom="float | int | color"
            android:valueTo="float | int | color"
            android:startOffset="int"
            android:repeatCount="int"
            android:repeatMode=["repeat" | "reverse"]
            android:valueType=["intType" | "floatType"]/>
    </set>
    

    <set><objectAnimator><animator>分别对应 AnimatorSet、ObjectAnimator 和 ValueAnimator。

    android:ordering中选择together表示子动画同时播放,选择sequentially表示子动画按前后顺序播放。默认值为together

    <animator>的属性与<objectAnimator>类似,只是没有android:propertyName属性,这里只列出<objectAnimator>属性

    • android:propertyName:属性动画的作用对象和属性名称
    • android:duration:动画持续时间
    • android:valueFrom:属性起始值
    • android:valueTo:属性结束值
    • android:startOffset:动画延迟播放时间
    • android:repeatCount:动画重复次数
    • android:repeatMode:动画重复模式
    • android:valueType:表示android:propertyName所指定的属性类型

    android:repeatCount的默认值为 0,为 -1 时表示无限循环。若android:propertyName指定属性表示的是颜色,则android:valueType不需要指定。

    使用该 XML

    AnimationSet set = (AnimatorSet) AnimatorInflater.loadAnimation(
        mContext, R.anim.property_animator);
    set.setTarget(button);
    set.start();
    

    插值器(Interpolator)与估值器(TypeEvaluator)

    Interpolator 被译为插值器,它的作用是根据时间流逝的百分比来计算当前属性值需要改变的百分比。在补间动画的介绍中,可以看到系统一共内置了九种插值器。

    TypeEvaluator 译为类型估值算法或者估值器,它的作用是根据当前百分比来计算改变后的属性值。系统内置有 IntEvaluator、FloatEvaluator 和 ArgbEvaluator(针对 Color 属性)。

    来看 IntEvaluator 的代码

    public class IntEvaluator implements TypeEvaluator<Integer> {
        public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
            int startInt = startValue;
            return (int) (startInt + fraction * (endValue - startInt));
        }
    }
    

    可以看到,IntEvaluator 会根据传入的估值 fraction 来计算当前需要变化的值。

    当想要自定义插值器时,需要实现 Interpolator 或 TimeInterpolator。自定义估值器需要实现 TypeEvaluator。

    文中流程图都来自 Carson_Ho 博客

    相关文章

      网友评论

          本文标题:Android 动画 | 艺术探索笔记

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