Android学习笔记之动画(一)——View动画

一、动画的分类

Android 的动画可以大致分为三种:View动画,帧动画,属性动画,其实帧动画也可以归类为View动画,只是它和常见的View动画(比如平移、旋转等)表现形式上略有不同而已。

  • View 动画:它是一种渐进式动画。View动画通过对场景里的对象进行不断地图像变化从而产生动画效果。
  • 帧动画:通过有序的播放一系列图像从而产生动画的效果,值得注意的是图片过多过大会导致OOM。
  • 属性动画:通过动态地改变对象属性值从而达到动画效果。值得注意的是属性动画是API11引入的新特性,在更低的版本中虽然可以通过兼容库来使用它,但本质还是View动画。

 二、使用动画时的注意事项

  1. OOM 问题:这个问题主要出现在帧动画中,当图片数量较多且图片较大时就容易出现OOM。
  2. 内存泄漏:通过属性动画我们可以实现一类无限循环的动画,这类动画需要在Activity退出时及时停止,否则将导致Activity无法释放从而造成内存泄漏。(View动画并不存在此问题)
  3. 尽量使用dp:在进行动画的过程中,要尽量使用dp,使用px会导致在不同的设备上有不同的效果。
  4. 开启硬件加速:使用动画的过程中,建议开启硬件加速,提高动画的流畅性。
  5. View动画的问题:View 动画实际上只对 View 的影像做动画,并不是真正地改变了 View 的状态,因此有时候会出现动画完成后View无法隐藏的现象,即 setVisibility(View.GONE) 失效了,这个时候只要调用 view.clearAnimation() 清除View动画即可解决此问题。
  6. 动画元素的交互:上一条有说 View 动画实际上操作的是 View 的影像,而非View本身。因此对于将view进行平移操作,在Android 3.0以前的系统上,不管是采用 View 动画还是属性动画,平移之后的新位置都无法触发点击事件,(因为在Android 3.0 以前通过兼容库使用的属性动画本质上还是View动画)而在原先的位置上仍然触发点击事件。从Android 3.0开始,属性动画的点击事件触发位置将会跟随View移动。 

三、插值器和估值器

在正式讲动画之前还需要了解两个概念:插值器和估值器。

  • 插值器 (TimeInterpolator):其作用为根据时间流逝的百分比计算出当前变化量的百分比,系统预置的有LinearInterpolator(线性插值器:匀速动画)、AccelerateDecelerateInterpolator(加速减速插值器:动画两头慢中间快)和DecelerateInterpolator(减速插值器:动画越来越慢)等。
  • 估值器 (TypeEvaluator): 其作用为根据当前变化量的百分比计算改变后值,系统预置的有 IntEvaluator(针对整形属性)、FloatEvaluator(针对浮点型属性)和 ArgbEvaluator(针对Color属性)。

 也就是说,借助插值器和估值器,我们可以在均匀的时间变化下,得出自己想要的非均匀的属性值变化,从而实现非匀速动画。

四、View动画

View动画的操作对象是View,它支持四种动画效果:平移动画,缩放动画,旋转动画以及透明度动画。虽然帧动画也属于View动画,但它和上述的四种动画效果相比,动画的形成原理并不相同,因此我打算分开来说。

4.1.通过XML文件实现View动画

1.首先在res/anim/目录下创建View动画的xml文件,文件名可以自定义。这里我创建了一个 translate_rotate_anim.xml 文件,如下:



    
    

其中标签表示动画集合,对应 AnimationSet 类,它可以包含若干个动画,并且它的内部也可以嵌套其他动画集合。在这里使用到了它的三个属性:

  • android:interpolator  表示动画集合所采用的插值器,默认值为@android:anim/accelerate_decelerate_interpolator
  • android:shareInterpolator  表示集合中的动画是否和集合共享同一个插值器。如果集合不指定插值器,那么子动画就需要单独指定所需的插值器或者使用默认值
  • android:fillAfter  动画结束后View是否停留在结束位置

这里只用到了平移和旋转的复合动画, 其中平移动画中使用到的属性含义如下:

  • android:duration  动画的持续时间,单位为ms
  • android:fromXDelta  表示x的起始值,类型为float
  • android:toXDelta  表示x的结束值,类型为float
  • android:fromYDelta  表示y的起始值,类型为float
  • android:toYDelta  表示y的结束值,类型为float

旋转动画中使用到的属性含义如下:

  • android:fromDegrees  表示旋转开始的角度,类型为float
  • android:toDegrees  表示旋转结束的角度,类型为float
  • android:pivotX  表示旋转轴点的X坐标
  • android:pivotY  表示旋转轴点的Y坐标

上述的pivot属性在缩放动画(标签为)中也是有使用到的,除此之外,它还使用到的其他属性含义如下:

  • android:fromXScale  表示水平方向缩放的起始值,类型为float
  • android:toXScale  表示水平方向缩放的结束值,类型为float
  • android:fromYScale  表示竖直方向缩放的起始值,类型为float
  • android:toYScale  表示竖直方向缩放的结束值,类型为float

最后透明度动画所使用的属性含义如下:

  • android:fromAlpha  表示透明度的起始值,类型为float
  • android:toAlpha  表示透明度的结束值,类型为float 

2.通过AnimationUtils工具类加载动画XML文件,然后为控件使用动画

private void bitmapTranslateAndRotate(){
    Animation animation = AnimationUtils.loadAnimation(this,R.anim.translate_rotate_anim);
    imageView.startAnimation(animation);
}

 4.2.通过代码来应用动画

这里以透明度动画为例,如下:

private void bitmapAlpha(){
    AlphaAnimation alphaAnimation = new AlphaAnimation(1,0);
    alphaAnimation.setDuration(3000);
    imageView.startAnimation(alphaAnimation);
}

在上面的代码中,创建了一个透明度动画,将一个ImageView的透明度在3秒内由1变为0。(由可见到不可见)

4.3.为View动画添加过程监听

animation.setAnimationListener(mAnimationListener);

具体来说可以监听动画的开始、结束以及重复播放事件,如下:

public static interface AnimationListener {
    void onAnimationStart(Animation animation);
    void onAnimationEnd(Animation animation);
    void onAnimationRepeat(Animation animation);
}

五、View动画在布局中的应用LayoutAnimation

LayoutAnimation 作用于 ViewGroup,它为ViewGroup指定一个动画 ,这样当它的子元素出场时都会具有这种动画效果。这里以ListView为例,具体实现步骤如下:

5.1.在res/anim/目录下新建布局动画文件,这里以list_view_anim.xml为例:


其中delay属性表示子元素开始动画的时间延迟,比如子元素入场动画时间周期为300ms,那么这里的0.5表示每个子元素都需要延迟150ms才能播放入场动画。总的来说,第一个子元素延迟150ms开始播放动画,第二个子元素延迟300ms开始播放,以此类推。animationOrder属性表示子元素动画的顺序,有三种选项:normal,reverse,random,分别代表着顺序播放,逆向播放和随机播放。最后的animation属性指定了子元素的具体入场动画。

5.2.编辑子元素的具体入场动画

这里就简单的展示一个从右边水平滑入的动画



    

5.3.为ListView指定LayoutAnimation

通过XML来设置动画的话,很简单直接在对应属性设置即可,如下:

android:layoutAnimation="@anim/list_view_anim"

也可以通过代码控制来设置LayoutAnimation,如下:

Animation animation = AnimationUtils.loadAnimation(this,R.anim.list_item_anim);
LayoutAnimationController controller = new LayoutAnimationController(animation);
controller.setDelay(0.5f);
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
mListView.setLayoutAnimation(controller);

六、帧动画

帧动画是顺序播放一组预先定好的图片,类似于电影播放。不同于View动画,系统提供了另外一个类 AnimationDrawable 来使用帧动画。

1.通过XML来定义一个 AnimationDrawable,在res/drawable/目录下新建一个frame_animation.xml文件如下:



    
    
    

2.然后将上述的 Drawable 作为 View 的背景并通过 Drawable 来播放动画即可:

imageView = findViewById(R.id.imageView);
imageView.setBackgroundResource(R.drawable.frame_animation);
AnimationDrawable drawable = (AnimationDrawable) imageView.getBackground();
drawable.start();

值得注意的是,要避免使用过多较大的图片防止OOM的发生。

你可能感兴趣的:(Android)