补间动画之 常用方法、动画集合、插值器和自定义补间动画

常用方法

谷歌的时候,发现有人罗列了 Animation 的常用方法,转载过来,以作备用。

  1. void cancel()
    作用:取消这个动画
  2. long computeDurationHint()
    返回值:计算一个动画的持续时间,返回一个以毫秒为单位的数据
  3. int getBackgroundColor()
    返回值:这个动画的背景颜色
  4. boolean getDetachWallpaper()
    返回值: 这个动画是否脱离壁纸运行的boolean值
  5. long getDuration()
    返回值:这个动画应该持续的时间
  6. boolean getFillAfter()
    返回值: 这个动画结束时画面是否停留在最后一帧 的boolean值
  7. boolean fillBefore()
    返回值: 这个动画结束时画面是否停留在第一帧 的boolean值
  8. Interpolator getInterpolator()
    返回值: 此动画的插值器类型
  9. int getRepeatCount()
    返回值: 动画要重复多少次
  10. int getRepeatMode()
    返回值:动画要重复的模式,例如重新开始,反向开始
  11. long getStartOffset()
    返回值:这个动画在调用start方法后延迟了多久才启动
  12. long getStartTime()
    返回值:这个动画调用start方法的时间
  13. boolean getTransformation(long currentTime, Transformation outTransformation, float scale)
    • 参数currentTime:传入某个动画时间
    • 参数outTransformation:获取传入时间点的变形的原始数据对象
    • 参数scale:缩放比例
    • 返回值:如果当前这个动画时间动画还在运行则返回true
  14. boolean getTransformation(long currentTime, Transformation outTransformation)
    • 参数currentTime:传入某个动画时间
    • 参数outTransformation:获取传入时间点的变形的原始数据对象
    • 返回值:如果当前这个动画时间动画还在运行则返回true
  15. int getZAdjustment()
    返回值:Animation在Z轴方向的顺序
  16. boolean hasEnded()
    返回值:动画是否已经结束
  17. boolean hasStarted()
    返回值:动画是否已经开始
  18. void initialize(int width, int height, int parentWidth, int parentHeight)
    • 参数width:动画对象的宽
    • 参数height:动画对象的高
    • 参数parentWidth:父控件的宽
    • 参数parentWidth:父控件的高
    • 作用:初始化动画对象以及父控件尺寸。
  19. boolean isFillEnabled()
    返回值:当前动画的使能填充属性。当该属性为true时,将执行setFillBefore和setFillAfter方法,否则将忽略setFillBefore和setFillAfter方法。
  20. boolean isInitialized()
    返回值:如果动画已经初始化 则返回true
  21. void reset()
    作用:重置动画到初始化状态
  22. void restrictDuration (long durationMillis)
    • 参数durationMillis:最大允许动画持续时间
    • 作用:调整动画持续时间,确保了重复执行,也不会持续的比给定的时间更长。
  23. void scaleCurrentDuration (float scale)
    • 参数scale:缩放比例
    • 作用:按一定的比例放大持续时间
  24. void setAnimationListener(Animation.AnimationListener listener)
    • 参数listener:动画监听
    • 作用:给一个动画设置监听,设置类似侦听动画的开始或动画重复的通知
  25. void setBackgroundColor(int bg)
    • 参数bg:Color的int值
    • 作用:设置动画的背景颜色
  26. void setDetachWallpaper(boolean detachWallpaper)
    • 参数detachWallpaper:是否脱离壁纸运行动画
    • 作用:如果为true,这个动画将会脱离背景运行,首先你要有个背景
  27. void setDuration(long durationMillis)
    • 参数durationMillis:动画的持续时间
    • 作用:设置一个动画的持续时间
  28. void setFillAfter(boolean fillAfter)
    • 参数fillAfter:动画是否停留在最后一帧
    • 作用:设置动画是否停留在最后一帧,为true则是停留在最后一帧
  29. void setFillBefore(boolean fillBefore)
    • 参数fillBefore:动画是否停留在第一帧
    • 作用:设置动画是否停留在第一帧,为true则是停留在第一帧
  30. void setFillEnabled(boolean fillEnabled)
    • 参数fillEnabled:动画是否使能填充
    • 作用:设置动画是否使能填充,为true将执行setFillBefore和setFillAfter方法,否则将忽略setFillBefore和setFillAfter方法。
  31. void setInterpolator(Context context, int resID)
    • 参数context:上下文环境
    • 参数resID:插值器R ID
    • 作用:设置动画插值器属性,使用XML设置
  32. void setInterpolator(Interpolator i)
    • 参数i:插值器
    • 作用:设置动画插值器属性,使用代码设置
  33. void setRepeatCount(int repeatCount)
    • 参数repeatCount:重复次数
    • 作用:设置动画重复次数
  34. void setRepeatMode(int repeatMode)
    • 参数repeatMode:重复类型,例如 重头开始,反向开始
    • 作用:设置动画重复时候的模式
  35. void setStartOffset(long startOffset)
    • 参数startOffset:延迟时间
    • 作用:当调用start方法后延迟一定时间开始
  36. void setStartTime(long startTimeMillis)
    • 参数startTimeMillis:动画开始时间
    • 作用:在特定的时间调用start方法
  37. void setZAdjustment(int zAdjustment)
    • 参数zAdjustment:Z轴方向的顺序(TOP,NORMAL,BOTTOM)
    • 作用:调整播放内容在Z轴方向的顺序
  38. void start()
    作用:第一次执行getTransformation方法的时候才会执行动画
  39. void startNow()
    作用:执行动画的主要方法,使用时需要先通过setAnimation方法为某一个View对象设置动画.
  40. boolean willChangeBounds()
    返回值:判断动画是否会改变视图的边界,ture为会改变
  41. boolean willChangeTransformationMatrix ()
    返回值:判断动画是否会改变移动变换的矩阵,ture为会改变
    从类 android.view.animation.Animation 继承的受保护的方法

以下方法不可以被调用使用,只是简单说明下是什么

  1. void applyTransformation(float interpolatedTime, Transformation t)
    • 参数interpolatedTime:动画进度时间值,取值范围在[0.0f-1.0f]
    • 参数t:动画某一帧中变形的原始数据
    • 作用:在自定义动画类的时候都要重写这个方法,主要作用是把一些属性组装成一个Transformation类,这个方法会被父类的getTransformation方法调用
  2. Animation clone ()
    返回值:此动画对象的副本
  3. void ensureInterpolator ()
    作用:这个动画有一个插值器
  4. void finalize ()
    作用:垃圾回收器要回收对象的时候,首先要调用这个类的finalize方法
  5. float getScaleFactor ()
    作用:返回每个类在动画中的缩放比例因子
  6. float resolveSize (int type, float value, int size, int parentSize)
    • 参数type:动画坐标的类型
    • 参数value:动画坐标的值
    • 参数size:动画对象的大小
    • 参数parentSize:动画对象的父对象的大小
    • 返回值:返回动画的尺寸

动画组合

我们可以将多个动画组合在一起,从而形成一个更加复杂绚丽的动画。

动画组合同样有两种方法:

Java 代码
组合动画需要用到 AnimationSet 对象,该对象接收一个参数:

  • 如果为 true,则集合中所有动画都使用与该集合相关联的插值器(interpolator)
  • 如果为 false,则每个动画使用各自的插值器

调用 AnimationSet 对象的 setInterpolator 方法可以为之设置插值器,关于插值器,后面会讲到

创建好 AnimationSet 之后,调用该对象的 addAnimation 就可以将若干个动画添加到集合中,然后再将这个集合设置到组件上,这个组件就可以同时展示若干个动画效果了。

public class MainActivity extends Activity {

    private ImageView imageView;
    private Button start, stop;

    private Animation alphaAnimation, rotateAnimation, scaleAnimation;
    private AnimationSet animationSet;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageView = findViewById(R.id.gif);
        start = findViewById(R.id.startAnimation);
        stop = findViewById(R.id.stopAnimation);

        alphaAnimation = new AlphaAnimation(1.0f, 0.0f);
        alphaAnimation.setDuration(3000);
        alphaAnimation.setRepeatCount(-1);
        alphaAnimation.setRepeatMode(Animation.REVERSE);

        rotateAnimation = new RotateAnimation(0, 360);
        rotateAnimation.setDuration(3000);
        rotateAnimation.setRepeatCount(-1);
        rotateAnimation.setRepeatMode(Animation.REVERSE);

        scaleAnimation = new ScaleAnimation(1.0f, 0.5f, 1.0f, 0.5f);
        scaleAnimation.setDuration(3000);
        scaleAnimation.setRepeatCount(-1);
        scaleAnimation.setRepeatMode(Animation.REVERSE);

        animationSet = new AnimationSet(true);
        animationSet.addAnimation(alphaAnimation);
        animationSet.addAnimation(rotateAnimation);
        animationSet.addAnimation(scaleAnimation);

    }

    @Override
    protected void onStart() {
        super.onStart();
        start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                imageView.startAnimation(animationSet);//启动动画
            }
        });

        stop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                animation.cancel();//取消动画
                imageView.clearAnimation();
            }
        });
    }
}

XML 文件定义
在 XML 文件中,我们可以使用 <set> 标签创建集合,在该集合中,假如若干单个动画,组成一个动画集合。

使用上和其他单个动画一样。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <alpha xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="3000"
        android:fromAlpha="1.0"
        android:toAlpha="0.0" />
    <rotate xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="2000"
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="-1"
        android:repeatMode="reverse"
        android:toDegrees="360" />
</set>

动画监听器

有时候我们需要监听动画进行到哪一步了,就可以为该动画设置一个 AnimationListener,该监听器可以监听到动画开始、结束、重复:

        animation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                Log.d("TTT", "动画开始了");
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                Log.d("TTT", "动画结束了");
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
                Log.d("TTT", "动画重复执行了");
            }
        });

插值器(Interpolator)

Android 提供了一个 Interpolator 接口来帮助我们控制动画的变化速度。

这个东西可以在 XML 当中通过 android:interpolator 属性指定,也可以直接调用 Animation 对象的 setInterpolator 方法指定。

Android 为我们提供了几个个实现类:

  • LinearInterpolator
    动画以均匀的速度改变

  • AccelerateInterpolator
    在动画开始的地方改变速度较慢,然后开始加速

  • AccelerateDecelerateInterpolator
    在动画开始、结束的地方改变速度较慢,中间加速

  • CycleInterpolator
    动画循环播放特定次数,变化速度按正弦曲线改变:Math.sin(2*mCycles*Math.PI*input)

  • DecelerateInterpolator
    在动画划开始的地方改变速度较快,然后开始加速

  • AnticipateInterpolator
    反向,先向相反方向改变一段再加速播放

  • AnticipateOvershootInterpolator
    开始的时候向后然后向前甩一定值后返回最后的值

  • BounceInterpolator
    跳跃,最快目的的值会跳跃,如目的值100,后面的值可能依次为85,77,70,80,90,100

  • OvershottInterpolator
    回弹,最后超出目的值然后缓慢改变到目的值

自定义补间动画

Android 提供了 Animation 作为补间动画抽象基类,并且为该抽象基类提供了 AlphaAnimation、RotateAnimation、ScaleAnimation、TranslateAnimation 四个实现类,这四个实现类只是补间动画的四种基本形式:透明度改变、旋转、缩放、位移。在实际项目中可能还需要一些更复杂的动画,比如让图片在“三维”空间内进行旋转动画等。这就需要开发者自己开发补间动画了。
自定义补间动画并不难,需要继承 Animation,继承 Animation 时关键是要重写该抽象基类的 applyTransformation(float interpolatedTime, TransFormation t) 方法,该方法中两个参数说明如下:

  • interpolatedTime
    代表了动画的事件进行比。不管动画实际的持续事件如何,当动画播放时,该参数总是自动从0变化到1;

  • Transformation
    代表了补间动画在不同时刻对图形或组件的变性程度。

从上面的介绍可以看出,实现自定义的关键就在于重写 applyTransformation() 方法时,根据 interpolatedTime 时间来动态的计算动画对图片或视图的变形程度。

Transformation 代表了对图片或视图的变形程度,该对象里封装了一个 Matrix 对象,对它所包装的 Matrix 进行位移、倾斜、旋转等变换,Transformation 将会控制对应的图片或视图进行相应的变换。

为了控制图片或视图进行三维控件的变换,还需要借助于 Android 提供的一个 Camera,这个 Camera 并非代表手机的摄像头,而是一个空间变换工具,作用优点类似于 Matrix,但功能更强大。

Camera提供了如下常用的方法。

  • getMatrix(Matrix matrix)
    将Camera所做的变换应用到指定matrix上

  • rotateX(float deg)
    是目标组件沿X轴旋转

  • rotateY(float deg)
    是目标组件沿Y轴旋转

  • rotateZ(float deg)
    是目标组件沿Z轴旋转

  • translate(float x, float y, float z)
    是目标组件在三维空间里进行位移变换

  • applyToCanvas(Canvas canvas)
    把Camera所做的变换应用到Canvas上

从上面的方法可以看出,Camera 主要用于支持三维空间的变换,那么手机中三维空间的坐标系统是怎样的呢?

当 Camera 控制图片或 View 沿 X、Y 或 Z 轴旋转时,被旋转的图片或 View 将会呈现出三维透视的效果

public class MyAnimation extends Animation
{
    private float centerX;
    private float centerY;
    // 定义动画的持续事件
    private int duration;
    private Camera camera = new Camera();
    public MyAnimation(float x, float y, int duration)
    {
        this.centerX = x;
        this.centerY = y;
        this.duration = duration;
    }
    @Override
    public void initialize(int width, int height
            , int parentWidth, int parentHeight)
    {
        super.initialize(width, height, parentWidth, parentHeight);
        // 设置动画的持续时间
        setDuration(duration);
        // 设置动画结束后效果保留
        setFillAfter(true);
        setInterpolator(new LinearInterpolator());
    }
    /*
     * 该方法的interpolatedTime代表了抽象的动画持续时间,不管动画实际持续时间多长,
     * interpolatedTime参数总是从0(动画开始时)~1(动画结束时)
     * Transformation参数代表了对目标组件所做的改变.
     */
    @Override
    protected void applyTransformation(float interpolatedTime
            , Transformation t)
    {
        camera.save();
        // 根据interpolatedTime时间来控制X、Y、Z上的偏移
        camera.translate(100.0f - 100.0f * interpolatedTime,
                150.0f * interpolatedTime - 150,
                80.0f - 80.0f * interpolatedTime);
        // 设置根据interpolatedTime时间在Y轴上旋转不同角度
        camera.rotateY(360 * (interpolatedTime));
        // 设置根据interpolatedTime时间在X轴上旋转不同角度
        camera.rotateX((360 * interpolatedTime));
        // 获取Transformation参数的Matrix对象
        Matrix matrix = t.getMatrix();
        camera.getMatrix(matrix);
        matrix.preTranslate(-centerX, -centerY);
        matrix.postTranslate(centerX, centerY);
        camera.restore();
    }
}

上面的程序中自定义动画的关键就是

// 设置根据interpolatedTime时间在Y轴上旋转不同角度
        camera.rotateY(360 * (interpolatedTime));
        // 设置根据interpolatedTime时间在X轴上旋转不同角度
        camera.rotateX((360 * interpolatedTime));

这两行代码,这两行代码将会根据动画的进行事件来控制 View 在 X、Y 轴上的旋转——这就会具体在三维空间内旋转的效果。

提供了上面的自定义动画类之后,接下来既可用该自定义动画类来控制图片,也可控制 View 组件,因为动画就是通过调用 View 的 startAnimation(Animation anim) 来启动的。下面是使用 MyAnimation 执行动画的程序代码。

public class MainActivity extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 获取ListView组件
        ListView list = (ListView) findViewById(R.id.list);
        WindowManager windowManager = (WindowManager)
                getSystemService(WINDOW_SERVICE);
        Display display = windowManager.getDefaultDisplay();
        DisplayMetrics metrice = new DisplayMetrics();
        // 获取屏幕的宽和高
        display.getMetrics(metrice);
        // 设置对ListView组件应用动画
        list.setAnimation(new MyAnimation(metrice.xdpi / 2
                , metrice.ydpi / 2, 3500));
    }
}

上面程序中的代码对 ListView 使用 MyAnimation 播放动画,这意味着程序中 ListView 将会以三维变换的动画方式出现,如下图所示

常用方法部分转载自:Android 之 TranslateAnimation类:位移动画类

Copyright© 2020-2022 li-xyz 冀ICP备2022001112号-1