动画

sky-mxc 总结 转载注明:https://sky-mxc.github.io

  • 帧动画
  • 补间动画
  • 属性动画
  • Interpolator

帧动画 FrameAnimation

其实就是一个Drawable ,将一系列的图片联合起来顺序的播放。形成动画效果。
帧动画本质就是一些图片的集合,要播放这个动画就必须将一系列的图片全部加载进内存中,所以帧动画的图片不易过大。

创建drawable文件

  • oneshot :是否只播放一次,
  • drawable :一帧的图片
  • duration :一帧播放的时间 毫秒单位
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="true">

    <item android:drawable="@mipmap/a_01" android:duration="200"/>
    <item android:drawable="@mipmap/a_02" android:duration="200"/>
    <item android:drawable="@mipmap/a_03" android:duration="200"/>
    <item android:drawable="@mipmap/a_04" android:duration="200"/>
    <item android:drawable="@mipmap/a_5" android:duration="200"/>
    <item android:drawable="@mipmap/a_6" android:duration="200"/>
</animation-list>

使用刚才的drawable文件做背景

<ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:background="@drawable/drawable_frame"
        android:clickable="true"
        android:onClick="onClick"/>

播放动画

//FrameAnimation  帧动画
((AnimationDrawable)image.getBackground()).start();

补间动画 tweenAnimation

主要是对view的内容完成一系列的图形变换(缩放,透明,旋转,平移)来实现动画效果。
具体来说就是 预先定义一些指令 ,这些指令指定了图形变换的类型,触发时间,持续时间。指令可以预先定义在xml文件中也可以源代码的方式定义。程序沿着时间线执行这些指令就可以实现动画效果。
Android中提供了 Animation,Interpolator,Transformation 等类具体实现Tween动画,
Animation类及其子类是动画的核心模块,它实现了 各种动画效果如 平移 旋转 缩放 改变透明度等等。
Tween动画的每一帧都根据Interpolator对view的内容做一次图像变换,因此Animation的核心工作是做变换(transformation);
Animation是基类 ,它记录了动画的通用属性和方法。主要的属性包括动画持续时间、重复次数、Interpolator等。

常用属性

  • duration :动画时间 毫秒
  • infinite :无限次
  • fillAfter 是否停顿在最后一针
  • repeatMode 重复模式 值:restart 重新开始 reserve 反复
  • repeatCount :重复次数
  • startOffset :开始延迟时间

常用Animation子类:

  • AlphaAnimation 改变Alpha值
  • TranslationAnimation 平移动画
  • RotateAnimation 旋转动画
  • ScaleAnimation 缩放动画
  • AnimationSet 动画集合

实例

补间动画 既可以使用 xml文件预先定义 也可以使用代码动态创建;
使用xml文件定义必须在 res/anim/目录下创建 文件;
可以使用 AnimationUtils的静态方法 loadAnimation()将动画文件加载

AlphaAnimation 透明度改变动画

定义 AlphaAnimation 文件
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="1"
    android:toAlpha="0.1"
    android:duration="2000"
    android:repeatCount="5"
    android:repeatMode="reverse">

</alpha>
加载 动画文件并播放
//AlphaAnimation xml定义
AlphaAnimation alphaAnimation = (AlphaAnimation) AnimationUtils.loadAnimation(this,R.anim.anim_alpha);
view.startAnimation(alphaAnimation);
代码创建
//AlphaAnimation 代码创建
    AlphaAnimation alphaAnimation1 = new AlphaAnimation(0.1f,0.8f);
    alphaAnimation1.setDuration(2000);
    alphaAnimation1.setStartOffset(100);
    alphaAnimation1.setFillAfter(true);
    alphaAnimation1.setRepeatCount(2);
    alphaAnimation1.setRepeatMode(Animation.REVERSE);
    view.startAnimation(alphaAnimation1);

TranslationAnimation 平移动画

  • fromXDelta X轴开始坐标
  • toXDelta X轴结束坐标
  • fromYDelta Y 轴开始坐标
  • toYDelta Y轴结束坐标
定义动画文件
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="2000"
    android:fromXDelta="0"
    android:toXDelta="300"
    android:repeatMode="reverse"
    android:repeatCount="3"
    android:fillBefore="true"
    android:fromYDelta="200"
    android:toYDelta="100">
</translate>
加载动画并播放
TranslateAnimation translateAnimation = (TranslateAnimation) AnimationUtils.loadAnimation(this,R.anim.anim_translation);
view.startAnimation(translateAnimation);
代码创建动画
TranslateAnimation translateAnimation1 = new TranslateAnimation(-10,100,0,0);
translateAnimation1.setInterpolator(new BounceInterpolator());
translateAnimation1.setDuration(2000);
view.startAnimation(translateAnimation1);

RotateAnimation 旋转动画

  • fromDegrees:起始角度
  • toDegrees:到达角度
  • pivotX:X轴中心点
  • pivotY:Y轴中心点

中心点取值模式:

  • 固定像素 50
  • 相对于自身 50%
  • 相对于父容器 50%p
定义动画文件
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toDegrees="90"
    android:fromDegrees="0"
    android:duration="2000"
    android:fillAfter="true">
</rotate>
加载动画并播放
RotateAnimation rotate = (RotateAnimation) AnimationUtils.loadAnimation(this,R.anim.anim_rotate);
view.startAnimation(rotate);
代码创建动画
//在右上角中心,0-180度
RotateAnimation rotate = new RotateAnimation(0, 180);
//(100,100)像素位中心
RotateAnimation rotate = new RotateAnimation(0, 180, 100, 100);
//相对于自身一半为中心
RotateAnimation rotate = new RotateAnimation(0, 180,Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);

沿中心旋转 45°

RotateAnimation rotateAnimation = new RotateAnimation(0,45,Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setInterpolator(new DecelerateInterpolator());
rotateAnimation.setDuration(2000);
rotateAnimation.setFillAfter(true);
view.startAnimation(rotateAnimation);

ScaleAnimation 缩放动画

  • fromXScale:X轴起始缩放值
  • fromYScale:Y轴起始缩放值
  • toXScale:X轴到达缩放值
  • toYScale:Y轴到达缩放值
  • 缩放值可以是缩放倍数,也可以是缩放到具体尺寸
定义动画文件
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXScale="0"
    android:toXScale="2"
    android:fromYScale="0"
    android:toYScale="3"
    android:duration="2000"
    android:pivotY="50%"
    android:pivotX="50%">

</scale>
加载动画并播放
ScaleAnimation scale = (ScaleAnimation) AnimationUtils.loadAnimation(this,R.anim.anim_scale);
view.startAnimation(scale);
代码创建动画
ScaleAnimation scale = new ScaleAnimation(0, 2, 0, 2);
ScaleAnimation scale = new ScaleAnimation(0, 2, 0, 2, 100, 100);
ScaleAnimation scale = new ScaleAnimation(0, 2, 0, 2,Animation.RELATIVE_TO_PARENT, 0.5f,Animation.RELATIVE_TO_PARENT, 0.5f);

AnimationSet 动画集合

定义动画文件
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="2000">

    <rotate android:pivotX="0"
        android:pivotY="0"
        android:fromDegrees="-180"
        android:toDegrees="0"/>

    <scale android:pivotX="50%"
        android:pivotY="50%"
        android:fromXScale="0"
        android:toXScale="1"
        android:fromYScale="0"
        android:toYScale="1"/>

</set>
加载动画并播放
Animation animation = AnimationUtils.loadAnimation(this,R.anim.anim_set);
view.startAnimation(animation);
代码创建动画
//子动画是否共用差值器
AnimationSet set = new AnimationSet(true);
set.addAnimation(new RotateAnimation(-180,0));
set.addAnimation(new ScaleAnimation(0,1,0,1,Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF,0.5f));
set.setDuration(2000);
set.setFillAfter(true);
view.startAnimation(set);

Interpolator

Interpolator 被用来修饰动画效果,定义动画的变化率,可以使存在的动画效果accelerated(加速),decelerated(减速),repeated(重复),bounced(弹跳)等。

常用的差值器
- LinearIntepolator 匀速效果
- DecelerateInterpolator 减速效果
- Accelerateinterpolator 加速效果
- CycleInterpolator 循环效果

- BouncedInterpolator 弹跳效果

Property Animation 属性动画

属性动画的用处有很多很多,我就列几个常用的方式把;具体参考官网文档:https://developer.android.com/guide/topics/graphics/prop-animation.html

补间动画并不能改变view真实的位置,只是形式上的位置改变。而属性动画会将view的真实位置改变。

属性动画定义必须在 res/animator目录下

ValueAnimation

valueType 常用三种取值:
- intType整数值、
- floatType浮点值、
- colorType颜色值、

定义动画文件

<?xml version="1.0" encoding="utf-8"?>
<animator xmlns:android="http://schemas.android.com/apk/res/android"
    android:valueFrom="2"
    android:valueTo="200"
    android:duration="2000"
    android:valueType="intType"
    android:interpolator="@android:interpolator/linear">

</animator>

加载动画 并添加 动画监听

属性动画 就是在 监听中去改变控件的属性的值 ,让控件 位置和形态的属性都发生真正的变化

ValueAnimator animator = (ValueAnimator) AnimatorInflater.loadAnimator(this,R.animator.animator_value);
                animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        //intType
                      int value= (int) animation.getAnimatedValue();
                        image.setTranslationY(value);
                      //  image.setTranslationX(value);

                        //floatType
//                        float alpha = (float) animation.getAnimatedValue();
//                        image.setAlpha(alpha);

                    }
                });

代码创建

//   ValueAnimator valueAnimator = ValueAnimator.ofFloat(1f,0.5f,0f);
PropertyValuesHolder alphaHolder = PropertyValuesHolder.ofFloat("alpha",1f,0.5f);
PropertyValuesHolder widthHolder = PropertyValuesHolder.ofInt("width",1,200);
PropertyValuesHolder rotateHolder = PropertyValuesHolder.ofFloat("rotate",0,180);
ValueAnimator valueAnimator = ValueAnimator.ofPropertyValuesHolder(alphaHolder,widthHolder,rotateHolder);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
//                       float value= (float) animation.getAnimatedValue();
//                        image.setAlpha(value);

      float alpha= (float) animation.getAnimatedValue("alpha");
        int width = (int) animation.getAnimatedValue("width");
        float rotate = (float) animation.getAnimatedValue("rotate");
        Log.e("MainActivity","alpha:"+alpha);
        Log.e("MainActivity","width:"+width);

        image.setAlpha(alpha);
       image.setMaxWidth(width);
        image.setMinimumWidth(width);
        image.setRotation(rotate);
    }
});
valueAnimator.setDuration(2000);
valueAnimator.start();

ObjectAnimator

大部分属性都和ValueAnimator相同,只多了对要控制改变的控件的属性的声明
propertyName:要控制的控件的属性名;
动画会直接修改制定属性名的属性

需要注意:设置了getter/setter方法的属性才能生效

定义动画文件

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:propertyName="rotation"
    android:valueFrom="0"
    android:valueTo="45"
    android:duration="2000"
    android:valueType="floatType">
    <!--
    rotation
        rotationY
        rotationX

    -->

</objectAnimator>

加载动画并设置播放动画的对象

ObjectAnimator object = (ObjectAnimator) AnimatorInflater.loadAnimator(this,R.animator.animator_object);
object.setTarget(image);
object.start();

代码创建动画

凡是 有get/set方法的属性都可以设置值

//  ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(image,"alpha",1f,0.2f);
ObjectAnimator objectAnimator = ObjectAnimator.ofInt(view,"backgroundColor", Color.RED,Color.YELLOW,Color.BLUE,Color.GREEN);
objectAnimator.setDuration(2000);
objectAnimator.setInterpolator(new BounceInterpolator());
objectAnimator.start();