Android 动画

Android动画

  • Android动画
    • 前言
    • 动画分类
    • 如何加载动画
      • 渐变动画
      • 帧动画
      • 属性动画


前言

之前一直没有系统地学习Android中的动画,每当编码需要动画效果的时候,总是很郁闷。虽然网上已经有很多相关的教程,但是自己还是做个总结:简单简洁!


动画分类

简单地说,动画就几种类型:渐变、平移、旋转等,Android中:

  • Tween Animation 渐变动画
    包含了渐变alpha、平移translate,旋转rotate,伸缩scale,这四个还是比较常见、基础的动画

  • Frame Animation 帧动画
    事先把所有的动画画面准备好,一帧一帧地放,相当于放电影

  • Property Animation 属性动画
    对View的属性进行变化,达到动画效果


如何加载动画

简单记住上面三种动画的属性就可以了,重要的是:如何加载动画。

渐变动画

对于渐变动画,如何将一个View(例如ImageView)实现渐变(或者缩放等)? 加载动画代码如下:

  • 先定义动画文件 /res/drawable/anim/alpha.xml

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <alpha
        android:duration="2000"
        android:fromAlpha="1.0"
        android:interpolator="@android:anim/linear_interpolator"
        android:toAlpha="0" />
set>

其中 duration 表示整个动画的时间,而对于一个渐变动作来说,会有一个起始透明值 fromAlpha 和结束透明值 toAlphainterpolator 是一个插补器,简单理解就是指定的动作效果,如实现加速、减速变化等

  • 对某个View加载动画
private ImageView photo;
...
Animation alpha = AnimationUtils.loadAnimation(MainActivity.this, R.anim.alpha); // 加载anim
photo.startAnimation(alpha); // 执行动画

以上是通过加载xml文件加载动画的,如果通过java来加载动画,则:

AlphaAnimation alpha = new AlphaAnimation(1.0f, 0);
alpha.setDuration(2000);
photo.startAnimation(alpha);

当然,有时候想同时两个动画一起加载,例如平移和渐变一起,通过 AnimationSet 类添加多个Animation实现:

// 渐变动画
Animation alpha = AnimationUtils.loadAnimation(MainActivity.this, R.anim.alpha);
alpha.setDuration(2000);

// 平移动画
TranslateAnimation translate = new TranslateAnimation(0, 160, 0, 160);
translate.setDuration(2000);

// 添加多个Animation实现同时加载多个动画
AnimationSet set = new AnimationSet(false);
set.addAnimation(alpha);
set.addAnimation(translate);
set.setFillAfter(true);

// 执行动画
photo.startAnimation(set);

对于渐变动画的属性,不同动画有不同的属性,这里列举,只需要大概记住,以后需要查找:

  • translate :位移肯定涉及到了坐标、位置
属性名 意义
fromXDelta X轴方向开始位置,可以是数值、%、%p(p表示相对于父布局)
toXDelta X轴方向结束位置,可以是数值、%、%p(p表示相对于父布局)
fromYDelta Y轴方向开始位置,可以是数值、%、%p(p表示相对于父布局)
toYDelta Y轴方向结束位置,可以是数值、%、%p(p表示相对于父布局)
  • scale:伸缩则涉及到了缩放比例
属性名 意义
fromXScale 起始的X方向上相对自身的缩放比例,浮点数,1.0表示本身
toXDelta 结束时的X方向上相对自身的缩放比例,浮点数,1.0表示本身
fromYDelta 起始的Y方向上相对自身的缩放比例,浮点数,1.0表示本身
toYDelta 结束时的X方向上相对自身的缩放比例,浮点数,1.0表示本身
pivotX 缩放时起点的X轴坐标,可以是数值、%、%p
pivotY 缩放时起点的Y轴坐标,可以是数值、%、%p
  • alpha:渐变会涉及到显示的透明度
属性名 意义
fromAlpha 动画开始时的透明度,浮点数,1.0表示不透明
toAlpha 动画结束时的透明度,浮点数,1.0表示不透明
  • rotate:旋转会涉及到旋转的角度
属性名 意义
fromDegrees 动画开始时旋转的角度位置,正代表顺时针度数
toDegrees 动画结束时旋转的角度位置,正代表顺时针度数
pivotX 旋转开始时的X轴坐标,可以是数值、%、%p
pivotY 旋转开始时的Y轴坐标,可以是数值、%、%p
  • 通用属性(也就是以上四者均有)
属性名 意义
duration 动画持续时间,以毫秒为单位
fillAfter 是否在动画结束时保持动画最后时的状态
fillBefore 是否在动画结束时还原动画最初时的状态
repeatCount 重复次数
repeatMode 有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍
interpolator 指定的动作效果,例如动作速度、弹跳等
  • interpolator 属性
属性名 意义
linear_interpolator 以常量速率改变
decelerate_interpolator 动画由快变慢
cycle_interpolator 动画循环播放特定的次数,速率改变沿着正弦曲线
bounce_interpolator 动画结束时弹起
overshoot_interpolator 向前甩一定值后再回到原来位置

总结: 以上就是渐变动画的加载,相对还是比较简单,通过编写xml文件,然后通过 AnimationUtils 加载动画,或者new一个Animation的类对象(如TranslateAnimation),最后通过 startAnimation() 方法执行动画。

帧动画

帧动画需要实现提供对应动画“每一帧”的画面,执行动画的时候,将每一个动画播放出来。
如何加载帧动画?——通过 AnimationDrawable 加载,需要实现在drawables编写对应的xml文件: /res/drawable/frame.xml


<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item android:drawable="@drawable/btn_star_off_disabled_holo_dark" android:duration="500" />
    <item android:drawable="@drawable/btn_star_off_disabled_holo_light" android:duration="500" />
    <item android:drawable="@drawable/btn_star_off_focused_holo_dark" android:duration="500" />
    <item android:drawable="@drawable/btn_star_off_focused_holo_light" android:duration="500" />
animation-list>

其中, oneshot 为true表示动画是只播放一次,并停在最后一帧,false则动画循环播放;该动画共4帧,每一帧持续500ms。
接下来通过 AnimationDrawable 来执行动画:

AnimationDrawable frame = (AnimationDrawable) getResources().getDrawable(R.drawable.frame);
photo.setBackgroundDrawable(anim);
frame.start();

属性动画

我觉得后面这文章的属性动画讲得很好:Android属性动画深入分析:让你成为动画牛人

属性动画主要针对属性进行变换从而实现动画效果,例如将ImageView的宽度增加(针对View的width)、位置的改变(针对View 的translateX)、透明度改变等,先大概说如何加载属性动画。

  • 确定对View的某个属性进行变换,例如偏移量translationX:
// 获取mView的translationX属性,将translationX属性从0变换到500
ObjectAnimator transAnim = ObjectAnimator.ofFloat(mView, "translationX", 0, 500);
transAnim.setDuration(200);
transAnim.start(); //执行动画
  • 原理
    属性动画要求动画作用的对象提供该属性的get和set方法,属性动画根据你传递的初始值和最终值,以动画的效果多次去调用set方法,每次传递给set方法的值都不一样,确切来说是随着时间的推移,所传递的值越来越接近最终值。当你对view的属性xxx做动画,如果想让动画生效,要同时满足两个条件:

    1. view必须要提供setXxx方法,如果动画的时候没有传递初始值,那么还要提供getXxx方法,因为系统要去拿xxx属性的初始值(如果这条不满足,程序直接Crash)
    2. object的setXxx对属性xxx所做的改变必须能够通过某种方法反映出来,比如会带来ui的改变(如果这条不满足,动画无效果但不会Crash)
  • 对任何属性执行动画
    Android中有一些view的属性并没有提供getter或setter,或者setter或getter并非直接操作view的对应属性,例如TextView的setWidth()和getWidth()并非直接操作width和height,所以需要通过获取其LayoutParams来改变其width和height属性。

    参照上文链接的文章,实现一个 ViewWrapper 类来封装我们的View的各个属性,从而能够通过属性动画来加载动画:

public static class ViewWrapper {

    private View targetView;

    public ViewWrapper(View targetView) {
        this.targetView = targetView;
    }

    public int getWidth() {
        return targetView.getLayoutParams().width;
    }

    public void setWidth(int width) {
        targetView.getLayoutParams().width = width;
        targetView.requestLayout();
    }

    public int getHeight() {
        return targetView.getLayoutParams().height;
    }

    public void setHeight(int height) {
        targetView.getLayoutParams().height = height;
        targetView.requestLayout();
    }

    public float getTranslationX() {
        return targetView.getTranslationX();
    }

    public void setTranslationX(float translationX) {
        targetView.setTranslationX(translationX);
    }

    public float getTranslationY() {
        return targetView.getTranslationY();
    }

    public void setTranslationY(float translationY) {
        targetView.setTranslationY(translationY);
    }
}

你可能感兴趣的:(Android,android,动画)