Android动画机制与使用技巧(二)——布局动画、插值器、自定义动画

Android布局动画

布局动画是指作用在ViewGroup上,给ViewGroup增加View时添加一个动画过渡效果。

最简单的布局动画是在ViewGroup的XML中,使用以下代码来打开布局动画。

android:animateLayoutChanges="true"

通过以上代码设置,当ViewGroup添加View时,子View会呈现逐渐显示的过渡效果,不过这个效果是Android默认的显示的过渡效果,且无法使用自定义的动画来替换这个效果。

另外,还可以通过使用LayoutAnimationController类来自定义一个子View的过渡效果,代码如下所示:

LinearLayout ll = (LinearLayout) findViewById(R.id.ll);//设置过渡动画ScaleAnimation sa = new ScaleAnimation(0, 1, 0, 1);sa.setDuration(2000);//设置布局动画的显示属性LayoutAnimationController lac = new LayoutAnimationController(sa, 0.5f);lac.setOrder(LayoutAnimationController.ORDER_NORMAL);//为ViewGroup设置布局动画ll.setLayoutAnimation(lac);

通过以上代码,给LinearLayout增加了一个视图动画,让子view在出现的时候,有一个缩放的动画效果。
LayoutAnimationController的第一个参数,是需要作用的动画,而第二个参数,则是每个子View显示的delay时间。当delay时间不为0时,可以设置子View显示的顺序,如下所示:

  • LayoutAnimationController.ORDER_NORMAL——顺序
  • LayoutAnimationController.ORDER_RANDOM——随机
  • LayoutAnimationController.ORDER_REVERSE——反序

Interpolators(插值器)

插值器是动画中一个非常重要的概念,通过插值器,可以定义动画变换速率,这一点非常类似物理中的加速度,其作用主要是控制目标变量的变化值进行对应的变化。同样一个动画变换起始值,在不同的插值器作用下,每个单位时间内所达到的变化值也是不一样的。例如一个位移动画,如果使用线性插值器,那么在持续时间内,单位时间所移动的距离都是一样的;如果使用加速度插值器,那么单位时间内所移动的距离先是越来越大后来是越来越小。总之它们的变换速率不一样,但最后都是在相同的规定时间内完成。

常用的插值器有以下几种:

  • AccelerateDecelerateInterpolator 在动画开始与结束的地方速率改变比较慢,在中间的时候加速
  • AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速
  • AnticipateInterpolator 开始的时候向后然后向前甩
  • AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值
  • BounceInterpolator 动画结束的时候弹起
  • CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线
  • DecelerateInterpolator 在动画开始的地方快然后慢
  • LinearInterpolator 以常量速率改变
  • OvershootInterpolator 向前甩一定值后再回到原来位置

用法很简单

ObjectAnimator anim= ObjectAnimator.ofFloat(view,"translationX",300); anim.setDuration(500); anim.setInterpolator(new AccelerateInterpolator()); anim.start(); 自定义动画

创建自定义动画非常简单,只需要实现它的applyTransformation方法的逻辑就可以了,不过通常情况下,还需要覆盖父类的initialize方法来实现一些初始化工作。applyTransformation方法有如下两个参数。

protected void applyTransformation(float interpolatedTime, Transformation t)

第一个参数interpolatedTime就是插值器的时间因子,这个因子是由动画当前完成的百分比和当前时间所对应的插值所计算出来的,取值范围为0到1.0。
第二个参数Transformation就是矩阵的封装类,一般使用这个类来获得当前的矩阵对象,代码如下:

Matrix matrix = t.getMatrix();

通过改变获得的matrix对象,可以将动画效果实现出来,而对于matrix的变换操作,基本可以实现任何效果的动画。

模拟电视关闭的效果

电视关闭的效果非常简单,就是让一个图片纵向比例不断缩小即可,对应的矩阵处理方法如下:

@Override protected void applyTransformation(float interpolatedTime, Transformation t) { Matrix matrix = t.getMatrix(); matrix.postScale(1, 1 – interpolatedTime, mCenterWidth, mCenterHeight); }

其中mCenterWidth, mCenterHeight就是缩放的中心点,当然,可以设置更精确的插值器,并将0到1.0的时间因子拆分为不同的过程,从而对不同的过程采用不同的动画效果,模拟更加真实的特效。

实现自定义的3D动画效果

结合矩阵,并使用Camera类来实现一个自定义的3D动画效果。要注意的是,这里的Camera并不是指手机中的相机,而是android.graphics.Camera中的Camera类,它封装了openGL的3D动画,从而可以方便地创建3D动画效果。把Camera想象成一个真实的摄像机,当物体固定在某处时,只要移动摄像机就能拍摄到具有立体感的图像,因此通过它可以实现各种3D效果。

自定义动画代码如下:

public class CustomAnim extends Animation { private int mCenterWidth; private int mCenterHeight; private Camera mCamera = new Camera(); private float mRotateY = 0.0f; @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); // 设置默认时长 setDuration(2000); // 动画结束后保留状态 setFillAfter(true); // 设置默认插值器 setInterpolator(new BounceInterpolator()); mCenterWidth = width / 2; mCenterHeight = height / 2; } // 暴露接口-设置旋转角度 public void setRotateY(float rotateY) { mRotateY = rotateY; } @Override protected void applyTransformation( float interpolatedTime, Transformation t) { final Matrix matrix = t.getMatrix(); mCamera.save(); // 使用Camera设置旋转的角度 mCamera.rotateY(mRotateY * interpolatedTime); // 将旋转变换作用到matrix上 mCamera.getMatrix(matrix); mCamera.restore(); // 通过pre方法设置矩阵作用前的偏移量来改变旋转中心 matrix.preTranslate(mCenterWidth, mCenterHeight); matrix.postTranslate(-mCenterWidth, -mCenterHeight); }}

使用Camera类实现动画效果非常简单,无非就是设置三个坐标轴的旋转角度,不过注意最后两行代码,可以改变旋转时的默认旋转中心。

两个实例效果如下:

Android动画机制与使用技巧(二)——布局动画、插值器、自定义动画 - 阿里云