Android 动画框架实现

·  阅读 2978

我平时项目开发必备框架

  1. Android上最强网络请求 Net
  2. Android上最强列表(包含StateLayout) BRV
  3. Android最强缺省页 StateLayout
  4. JSON和长文本日志打印工具 LogCat
  5. 支持异步和全局自定义的吐司工具 Tooltip
  6. 开发调试窗口工具 DebugKit
  7. 一行代码创建透明状态栏 StatusBar

这里我说是指的Google对于常用的动画效果进行的封装. 有很多炫酷的效果可以通过这些封装快速实现.

LayoutAnimationController

用于支持列表控件(RecyclerView和ListView)的Item动画效果

属性:

  1. 动画

    传入动画XML文件来决定加载动画

  2. 动画顺序

    有三个值: normal 按照正常顺序 reverse 从最后的控件开始加载动画 random 随机顺序

  3. 延迟时间

    毫秒值单位, 表示每个条目的加载时间相差多少毫秒

  4. 动画插值器

布局动画使用方式有两种:

  1. 布局中引用动画

在anim目录下创建XML

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:animation="@anim/animation_set"
    android:animationOrder="normal"
    android:delay="300">
</layoutAnimation>
复制代码

在布局XML中引用XML动画

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent"
    android:id="@+id/ll_root"
    android:gravity="center"
    android:layoutAnimation="@anim/animation_layout"
    >
复制代码
  1. 代码中引用动画
//通过加载XML动画设置文件来创建一个Animation对象;
Animation animation=AnimationUtils.loadAnimation(this, R.anim.list_anim);
//得到一个LayoutAnimationController对象;
LayoutAnimationController mLayoutAnimationController = new LayoutAnimationController(animation);
//设置控件显示的顺序;
mLayoutAnimationController.setOrder(LayoutAnimationController.ORDER_REVERSE);
//设置控件显示间隔时间;
mLayoutAnimationController.setDelay(1);
//为ListView设置LayoutAnimationController属性;
mList.setLayoutAnimation(mLayoutAnimationController);
复制代码

Tip: 注意布局动画要么在onCreate方法中执行, 如果在其他地方执行就需要你手动执行布局对象的invalidate()方法.

该函数属于ViewGroup下的动画效果

void setLayoutAnimation (LayoutAnimationController controller)
复制代码

LayoutTransitionController

参考网上写法我出现了Crash情况. 并且无法直接运行ExampleDemo. 指向ObjectAnimator的View参数不能为Null, 报空指针异常. 我没有解决故也不做讲解.

不过通过在XML布局中给ViewGroup添加如下属性可以启用默认的动画效果

android:animateLayoutChanges="true"
复制代码

ViewAnimationUtils

揭示效果也可以看做是控制一个控件的圆角变化动画效果. ViewAnimationUtils这个类只有一个方法:

Animator createCircularReveal (View view, 
                int centerX, 
                int centerY, 
                float startRadius, 
                float endRadius)
复制代码
// 创建环形显示动画
Animator animator = ViewAnimationUtils.createCircularReveal(mBtnExtract, mBtnExtract.getWidth() / 2, mBtnExtract.getHeight() / 2, mBtnExtract.getWidth() / 4, mBtnExtract.getHeight() / 4);

animator.setInterpolator(new LinearInterpolator());
animator.setDuration(1000);
animator.start();
复制代码

overridePendingTransition

自定义进入下一个Activity和退出当前Activity的动画XML文件, 不需要考虑兼容问题.

注意一定要在startActivity或者finishd的后面调用才有效.

overridePendingTransition(int enterAnim, int exitAnim); // 0表示不显示动画
复制代码
  • enterAnim 界面进入动画
  • exitAnim 界面退出动画

ViewPropertyAnimator

视图类View提供一个animate()方法方便快速的设置常用动画

ViewPropertyAnimator animate ()
复制代码

ViewPropertyAnimator这个类基本上可以设置View的所有属性, 方法看名字就可以全部理解了

其中很多方法有带"By"和不带的同名方法. 带"By"相当于相对属性值, 不带就是绝对属性值.

ViewPropertyAnimator translationX (float value)
ViewPropertyAnimator translationXBy (float value)
复制代码

Tip: 如果使用链式调用可以同时执行多个动画效果.

view.animate()  
        .scaleX(1)
        .scaleY(1)
        .alpha(1);
复制代码

监听器

ViewPropertyAnimator setListener (Animator.AnimatorListener listener)
复制代码

AnimatorListener包含四种回调

// 在动画被取消的时候
abstract void	onAnimationCancel(Animator animation)

// 无论动画是否取消, 结束的时候都会回调
abstract void	onAnimationEnd(Animator animation)

default void	onAnimationEnd(Animator animation, 
                               boolean isReverse) // 是否重复

// 动画重复的时候回调
abstract void	onAnimationRepeat(Animator animation) 

// 动画开始
abstract void	onAnimationStart(Animator animation)

default void	onAnimationStart(Animator animation, 
                                 boolean isReverse) // 动画是否重复
复制代码

还有一种一次性的回调, 如果ViewPropertyAnimator对象再次执行动画并不会回调. 并且withEndAction()在动画被取消的时候不会回调. 这和onAnimationEnd()不同.

ViewPropertyAnimator withEndAction (Runnable runnable)

ViewPropertyAnimator withStartAction (Runnable runnable)
复制代码

更新

该回调会在大概每10毫秒执行一次

ViewPropertyAnimator setUpdateListener (ValueAnimator.AnimatorUpdateListener listener)
复制代码

DynamicAnimation

DynamicAnimation是在API25出现的基于物理运动效果的动画, 属于抽象类. 官方目前只有SpringAnimation继承该类. 使用SpringAnimation的好处是让动画显得不那么生硬, 可能有人会说动画插值器也可以. 但是鉴于动画插值器涉及到坐标轴算法Google为了让更多人能够方便的优化自己的动画效果才出现了DynamicAnimation.

官方说明

以下介绍官方示例


SpringForce spring = new SpringForce(0)
  .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)
  .setStiffness(SpringForce.STIFFNESS_LOW);

final SpringAnimation anim = new SpringAnimation(mImag, DynamicAnimation.SCALE_Y)
  .setMinValue(0).setSpring(spring).setStartValue(1);
anim.start();
复制代码

SpringForce

通过SpringAnimation的方法设置

SpringAnimation setSpring (SpringForce force)
复制代码

或者不创建SpringForce直接通过SpringAnimation得到一个SpringForce实例也可以

SpringForce getSpring ()
复制代码

是控制SpringAnimation的力度, 分别控制三种弹性特性

  • 阻尼比例
  • 僵硬程度

创建构造方法

SpringForce (float finalPosition) //  最终位置
复制代码

SpringForce可以决定动画的最终值却无法决定起始值(默认起始值是当前属性值), 起始值也可以由SpringAnimation设置.

阻尼比例设置(阻尼具体提现在摆动次数)

SpringForce setDampingRatio (float dampingRatio)
复制代码

SpringForce内部提供四种阻尼比例:

public static final float DAMPING_RATIO_HIGH_BOUNCY = 0.2f;  
 
public static final float DAMPING_RATIO_MEDIUM_BOUNCY = 0.5f; // 默认值
 
public static final float DAMPING_RATIO_LOW_BOUNCY = 0.75f; 
 
public static final float DAMPING_RATIO_NO_BOUNCY = 1f;
复制代码

僵硬值具体提现在摆动时间上

SpringForce setStiffness (float stiffness)
复制代码

同样SpringForce也提供了四种僵硬值:

public static final float STIFFNESS_HIGH = 10_000f;
 
public static final float STIFFNESS_MEDIUM = 1500f; // 默认值
 
public static final float STIFFNESS_LOW = 200f;
 
public static final float STIFFNESS_VERY_LOW = 50f;
复制代码

Spring的构造方法

SpringAnimation (View v,  // 目标视图
                DynamicAnimation.ViewProperty property) // 属性值, 后面将重点讲解

SpringAnimation (View v, 
                DynamicAnimation.ViewProperty property, 
                float finalPosition)
复制代码

ViewProperty是内部的一个抽象类

从源码可以看出主要作用就是设置属性值

DynamicAnimation提供一系列默认的ViewProperty

TRANSLATION_X
TRANSLATION_Y
TRANSLATION_Z
SCALE_X
SCALE_Y
ROTATION
ROTATION_X
ROTATION_Y
X
Y
Z
ALPHA
SCROLL_X
SCROLL_Y
复制代码

SpringAnimation在运动时候也可以修改最终位置

void animateToFinalPosition (float finalPosition)
复制代码

AnimatedStateListDrawable

注意和StateListAnimator有所区分, 限制api21;

StateListAnimator 即 <selector>标签中的item从Drawable换成了animation

<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
 
    <item
        android:id="@+id/on"
        android:state_activated="true">
        <bitmap
            android:src="@drawable/ic_heart_100"/>
    </item>
 
    <item
        android:id="@+id/off">
        <bitmap
            android:src="@drawable/ic_heart_0"/>
    </item>
 
    <transition
        android:fromId="@+id/on"
        android:toId="@+id/off"
        android:drawable="@drawable/animation_emptying">
    </transition>
 
    <transition
        android:fromId="@id/off"
        android:toId="@id/on"
        android:drawable="@drawable/animation_filling">
    </transition>
 
</animated-selector>
复制代码

item可以指定起始和结束的位图以及触发状态

transition可以指定当触发状态时执行什么动画

更多动画阅读我的其他文章

  • 矢量动画
  • 转场动画
  • ViewAnimator