美文网首页
Android 动画系列一 视图动画(ViewAnimation

Android 动画系列一 视图动画(ViewAnimation

作者: 赫丹 | 来源:发表于2018-09-11 11:48 被阅读72次

一、概述

Android3.0以前的原生动画
视图动画,也叫Tween(补间)动画可以在一个视图容器内执行一系列简单变换(位置、大小、旋转、透明度)。譬如,如果你有一个TextView对象,您可以移动、旋转、缩放、透明度设置其文本,当然,如果它有一个背景图像,背景图像会随着

二、相关属性详解

2-1 Animation(Animation抽象类是所有补间动画类的基类,基类中提供的一些通用的动画属性方法)

xml属性 java方法 说明
android:detachWallpaper setDetachWallpaper(boolean) 是否在壁纸上运行
android:duration setDuration(long) 动画持续时间,毫秒为单位
android:fillAfter setFillAfter(boolean) 控件动画结束时是否保持动画最后的状态
android:fillBefore setFillBefore(boolean) 控件动画结束时是否还原到开始动画前的状态
android:fillEnabled setFillEnabled(boolean) 与android:fillBefore效果相同
android:interpolator setInterpolator(Interpolator) 设定插值器(指定的动画效果,譬如回弹等
android:repeatCount setRepeatCount(int) 重复次数
android:repeatMode setRepeatMode(int) 重复类型有两个值,reverse表示倒序回放,restart表示从头播放
android:startOffset setStartOffset(long) 调用start函数之后等待开始运行的时间,单位为毫秒
android:zAdjustment setZAdjustment(int) 表示被设置动画的内容运行时在Z轴上的位置(top/bottom/normal),默认为normal
无论那种补间动画都具备以上的属性,可以是一个或多个,除此自外每种动画都有一些特有的属性;

2-2 AlpahAnimation(透明度动画)

xml属性 java方法 说明
android:fromAlpha AlphaAnimation(float fromAlpha, …) 动画开始的透明度(0.0到1.0,0.0是全透明,1.0是不透明)
android:toAlpha AlphaAnimation(…, float toAlpha) 动画结束的透明度(0.0到1.0,0.0是全透明,1.0是不透明)

2-3 RotateAnimation(旋转动画)

xml属性 java方法 说明
android:fromDegrees RotateAnimation(float fromDegrees, …) 旋转开始角度,正代表顺时针度数,负代表逆时针度数
android:toDegrees RotateAnimation(…, float toDegrees, …) 旋转结束角度,正代表顺时针度数,负代表逆时针度数
android:pivotX RotateAnimation(…, float pivotX, …) 缩放起点X坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点)
android:pivotY RotateAnimation(…, float pivotY) 缩放起点Y坐标,同上规律

2-3 ScaleAnimation(缩放动画)

xml属性 java方法 说明
android:fromXScale ScaleAnimation(float fromX, …) 初始X轴缩放比例,1.0表示无变化
android:toXScale ScaleAnimation(…, float toX, …) 结束X轴缩放比例
android:fromYScale ScaleAnimation(…, float fromY, …) 初始Y轴缩放比例
android:toYScale ScaleAnimation(…, float toY, …) 结束Y轴缩放比例
android:pivotX ScaleAnimation(…, float pivotX, …) 缩放起点X轴坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点)
android:pivotY ScaleAnimation(…, float pivotY) 缩放起点Y轴坐标,同上规律

2-4 TranslateAnimation(移动动画)

xml属性 java方法 说明
android:fromXDelta TranslateAnimation(float fromXDelta, …) 起始点X轴坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点)
android:fromYDelta TranslateAnimation(…, float fromYDelta, …) 起始点Y轴从标,同上规律
android:toXDelta TranslateAnimation(…, float toXDelta, …) 结束点X轴坐标,同上规律
android:toYDelta TranslateAnimation(…, float toYDelta) 结束点Y轴坐标,同上规律

2-5 AnimationSet

AnimationSet继承自Animation,是上面四种的组合容器管理类,没有自己特有的属性,他的属性继承自Animation,所以特别注意,当我们对set标签使用Animation的属性时会对该标签下的所有子控件都产生影响。

三、相关方法详解

3-1 Animation类

方法 说明
reset() 重置Animation的初始化
cancel() 取消Animation动画
start() 开始Animation动画
setAnimationListener(AnimationListener listener) 给当前Animation设置动画监听
hasStarted() 判断当前Animation是否开始
hasEnded() 判断当前Animation是否结束

3-2 View类的常用动画操作方法

方法 说明
startAnimation(Animation animation) 对当前View开始设置的Animation动画
clearAnimation() 取消当View在执行的Animation动画

3-3 注意事项

补间动画执行之后并未改变View的真实布局属性值。切记这一点,譬如我们在Activity中有一个View在屏幕上方,我们设置了平移动画移动到屏幕下方然后保持动画最后执行状态呆在屏幕下方,这时如果点击屏幕下方动画执行之后的View是没有任何反应的,而点击原来屏幕上方没有Button的地方却响应的是点击View的事件。

四、使用方法

4-1 Alpha

方法1:在XML中设置
  • 1、在路径res/anim的文件夹里创建alpha.xml
  • 2、根据动画效果设置不同的动画参数,从而实现透明动画效果。代码如下
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:fillAfter="true"
    android:fromAlpha="1"
    android:repeatCount="5"
    android:repeatMode="reverse"
    android:startOffset="500"
    android:toAlpha="0"
    android:interpolator="@android:anim/overshoot_interpolator"
    ></alpha>
  • 3、在java代码中创建对象并播放动画
Animation  alphaAnimation = AnimationUtils.loadAnimation(this, R.anim.alpha);
 tween_img.startAnimation(alphaAnimation);
//取消动画
tween_img.clearAnimation();
方法2:在java代码中设置(效果同上)
AlphaAnimation  alphaAnimation = new AlphaAnimation(1, 0);
        alphaAnimation.setDuration(3000);
        alphaAnimation.setStartOffset(500);
        alphaAnimation.setFillAfter(false);
        alphaAnimation.setRepeatCount(5);
        alphaAnimation.setRepeatMode(Animation.RESTART);
        alphaAnimation.setInterpolator(new LinearInterpolator());
       tween_img.startAnimation(alphaAnimation);
      //取消动画
      tween_img.clearAnimation();

4-2 Rotate

方法1:在XML中设置
  • 1、在路径res/anim的文件夹里创建rotate.xml
  • 2、根据动画效果设置不同的动画参数,从而实现透明动画效果。代码如下
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:fillAfter="true"
    android:fillBefore="true"
    android:fromDegrees="0"
    android:interpolator="@android:anim/anticipate_interpolator"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="5"
    android:repeatMode="reverse"
    android:startOffset="500"
    android:toDegrees="180"
    ></rotate>
  • 3、在java代码中创建对象并播放动画
 RotateAnimation rotateAnimation = AnimationUtils.loadAnimation(this, R.anim.rotate); 
 tween_img.startAnimation(rotateAnimation);
//取消动画
tween_img.clearAnimation();
方法2:在java代码中设置(效果同上)
//        伸缩模式,可以取值为ABSOLUTE、RELATIVE_TO_SELF、RELATIVE_TO_PARENT
//        Animation.ABSOLUTE为绝对值 其他为百分比。
    RotateAnimation rotateAnimation = new RotateAnimation(0, 270, Animation.RELATIVE_TO_SELF, 0.5f, 
    Animation.RELATIVE_TO_SELF, 0.5f);
        rotateAnimation.setDuration(3000);
        rotateAnimation.setStartOffset(500);
        rotateAnimation.setFillAfter(false);
        rotateAnimation.setRepeatCount(5);
        rotateAnimation.setRepeatMode(Animation.REVERSE);
        rotateAnimation.setInterpolator(new LinearInterpolator());
       tween_img.startAnimation(rotateAnimation);
      //取消动画
      tween_img.clearAnimation();

4-3 Scale

方法1:在XML中设置
  • 1、在路径res/anim的文件夹里创建scale.xml
  • 2、根据动画效果设置不同的动画参数,从而实现透明动画效果。代码如下
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:fillAfter="true"
    android:fillBefore="true"
    android:interpolator="@android:anim/overshoot_interpolator"
    android:repeatCount="5"
    android:repeatMode="reverse"
    android:startOffset="500"

    android:fromXScale="1"
    android:fromYScale="1"
    android:toXScale="0"
    android:toYScale="0"
    android:pivotY="50%"
    android:pivotX="50%"
    ></scale>
  • 3、在java代码中创建对象并播放动画
 ScaleAnimation scaleAnimation = AnimationUtils.loadAnimation(this, R.anim.scale);
 tween_img.startAnimation(scaleAnimation);
//取消动画
tween_img.clearAnimation();
方法2:在java代码中设置(效果同上)
//        伸缩模式,可以取值为ABSOLUTE、RELATIVE_TO_SELF、RELATIVE_TO_PARENT
//        Animation.ABSOLUTE为绝对值 其他为百分比。
    AcaleAnimation scaleAnimation = new ScaleAnimation(1, 0, 1, 0, Animation.RELATIVE_TO_SELF, 0.5f, 
    Animation.RELATIVE_TO_SELF, 0.5f);
        scaleAnimation.setDuration(3000);
        scaleAnimation.setStartOffset(500);
        scaleAnimation.setFillAfter(false);
        scaleAnimation.setRepeatCount(5);
        scaleAnimation.setRepeatMode(Animation.REVERSE);
        scaleAnimation.setInterpolator(new LinearInterpolator());
       tween_img.startAnimation(scaleAnimation);
      //取消动画
      tween_img.clearAnimation();

4-4 Translate

方法1:在XML中设置
  • 1、在路径res/anim的文件夹里创建translate.xml
  • 2、根据动画效果设置不同的动画参数,从而实现透明动画效果。代码如下
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:fillAfter="true"
    android:fillBefore="true"
    android:interpolator="@android:anim/overshoot_interpolator"
    android:repeatCount="5"
    android:repeatMode="reverse"
    android:startOffset="500"

   android:fromXDelta="0"
    android:fromYDelta="0"
    android:toXDelta="50%p"
    android:toYDelta="0"
    ></translate>
  • 3、在java代码中创建对象并播放动画
 TranslateAnimation  translateAnimation = AnimationUtils.loadAnimation(this, R.anim.translate);
 tween_img.startAnimation(translateAnimation);
//取消动画
tween_img.clearAnimation();
方法2:在java代码中设置(效果同上)
//        伸缩模式,可以取值为ABSOLUTE、RELATIVE_TO_SELF、RELATIVE_TO_PARENT
//        Animation.ABSOLUTE为绝对值 其他为百分比。
    TranslateAnimation  translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, -0.5f, Animation.RELATIVE_TO_PARENT, 0.5f,
                Animation.RELATIVE_TO_SELF, 0f,
                Animation.ABSOLUTE, 0);
        translateAnimation.setDuration(3000);
        translateAnimation.setStartOffset(500);
        translateAnimation.setFillAfter(true);
        translateAnimation.setFillAfter(false);
        translateAnimation.setRepeatCount(5);
        translateAnimation.setRepeatMode(Animation.REVERSE);
        translateAnimation.setInterpolator(new LinearInterpolator());
       tween_img.startAnimation(translateAnimation);
      //取消动画
      tween_img.clearAnimation();

4-5 Set

方法1:在XML中设置
  • 1、在路径res/anim的文件夹里创建set.xml
  • 2、根据动画效果设置不同的动画参数,从而实现透明动画效果。代码如下
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fillAfter="true">
    <rotate
        android:duration="5000"
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toDegrees="360" />
    <translate
        android:duration="5000"
        android:fromXDelta="-50%p"
        android:fromYDelta="0"
        android:toXDelta="50%p"
        android:toYDelta="0" />
    <alpha
        android:duration="5000"
        android:fromAlpha="1.0"
        android:toAlpha="0.0" />
    <scale
        android:duration="5000"
        android:fromXScale="1.0"
        android:fromYScale="1.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="0.5"
        android:toYScale="0.5" />
</set>
  • 3、在java代码中创建对象并播放动画
 AnimationSet  setAnimation = AnimationUtils.loadAnimation(this, R.anim.set);
 tween_img.startAnimation(setAnimation);
//取消动画
tween_img.clearAnimation();
方法2:在java代码中设置(效果同上)
 //true使用集合的插值器,,false使用动画自己的插值器
       AnimationSet animationSet = new AnimationSet(true);
        animationSet.addAnimation(translateAnimation);
        animationSet.addAnimation(alphaAnimation);
//        animationSet.addAnimation(rotateAnimation);
//        animationSet.addAnimation(scaleAnimation);
        animationSet.setDuration(1000);
        animationSet.setFillAfter(false);
       tween_img.startAnimation(animationSet);
      //取消动画
      tween_img.clearAnimation();

五、动画监听

  • Animation类通过监听动画开始 / 结束 / 重复时刻来进行一系列操作,如跳转页面等等
  • 通过在 Java 代码里setAnimationListener()方法设置
 animation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                //动画开始回调
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                //动画结束回调
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
                //重复执行动画回调

            }
        });

六、插值器(Interpolator)

6-1 插值器
  • 1、作用:设置 属性值 从初始值过渡到结束值 的变化规律(如匀速、加速 & 减速 等等或者是明确了动画的变化模式)
  • 2、应用场景:实现非线性运动的动画效果
  • 3、系统提供的插值器(从源码中看,所有的插值器都实现Interpolator接口)
java类 xml id值 说明
AccelerateDecelerateInterpolator @android:anim/accelerate_decelerate_interpolator 动画始末速率较慢,中间加速
AccelerateInterpolator @android:anim/accelerate_interpolator 动画开始速率较慢,之后慢慢加速
AnticipateInterpolator @android:anim/anticipate_interpolator 先退后再加速前进
AnticipateOvershootInterpolator @android:anim/anticipate_overshoot_interpolator 先退后再加速前进,超出终点后再回终点
BounceInterpolator @android:anim/bounce_interpolator 动画结束时弹球效果
CycleInterpolator @android:anim/cycle_interpolator 循环播放速率改变为正弦曲线
DecelerateInterpolator @android:anim/decelerate_interpolator 动画开始快然后慢
LinearInterpolator @android:anim/linear_interpolator 动画匀速改变
OvershootInterpolator @android:anim/overshoot_interpolator 向前弹出一定值之后回到原来位置
插值器主要用于android动画中,用于改变动画变化的速率。Android自定义了很多种插值器,可以满足一般动画的需求。不过,当用户对自己的动画有很精细的要求,那就需要我们自己来定义动画的Interpolator了
6-2 自定义插值器
一、 基于三次方贝塞尔曲线的插值器
1、先使用贝塞尔曲线数值生成工具来获取想要的曲线数值
2、次方曲线插值器.(基于三次方贝塞尔曲线)
public class BezierInterpolator implements Interpolator {

    private final static int ACCURACY = 4096;
    private int mLastI = 0;
    private final PointF mControlP1 = new PointF();
    private final PointF mControlP2 = new PointF();

    @Override
    public float getInterpolation(float input) {
        float t = input;

        for (int i = mLastI; i < ACCURACY; i++) {
            t = 1.0f * i / ACCURACY;
            double x = cubicCurves(t, 0, mControlP1.x, mControlP2.x, 1);
            if (x >= input) {
                mLastI = i;
                break;
            }
        }
        double value = cubicCurves(t, 0, mControlP1.y, mControlP2.y, 1);
       /* if (value > 0.999d) {
            value = 1;
            mLastI = 0;
        }*/
        return (float) value;
    }

    public BezierInterpolator(float x1, float y1, float x2, float y2) {
        mControlP1.x = x1;
        mControlP1.y = y1;
        mControlP2.x = x2;
        mControlP2.y = y2;
    }

    //求三次贝塞尔曲线(四个控制点)一个点某个维度的值
    public double cubicCurves(double t, double value0, double value1, double value2, double value3) {
        double value;
        double u = 1 - t;
        double tt = t * t;
        double uu = u * u;
        double uuu = uu * u;
        double ttt = tt * t;

        value = uuu * value0;
        value += 3 * uu * t * value1;
        value += 3 * u * tt * value2;
        value += ttt * value3;
        return value;
    }
}
3、使用方法同上,只需把获取的曲线控制点传入即可
二、通过实现Interpolator类来实现
  • 我们先来看看源码,看LinearInterpolator(匀速进行)是怎么实现的:
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {

    public LinearInterpolator() {
    }

    public LinearInterpolator(Context context, AttributeSet attrs) {
    }

    public float getInterpolation(float input) {
        return input;
    }

    /** @hide */
    @Override
    public long createNativeInterpolator() {
        return NativeInterpolatorFactoryHelper.createLinearInterpolator();
    }
}
  • 再来看看稍微复杂一点的AccelerateDecelerateInterpolator(动画始末速率较慢,中间加速)是怎么实现的:
public class AccelerateDecelerateInterpolator extends BaseInterpolator
        implements NativeInterpolatorFactory {
    public AccelerateDecelerateInterpolator() {
    }

    @SuppressWarnings({"UnusedDeclaration"})
    public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) {
    }

    public float getInterpolation(float input) {
        return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
    }

    /** @hide */
    @Override
    public long createNativeInterpolator() {
        return NativeInterpolatorFactoryHelper.createAccelerateDecelerateInterpolator();
    }
  • 分析
    // input的运算逻辑如下:
    // 使用了余弦函数,因input的取值范围是0到1,那么cos函数中的取值范围就是π到2π。
    // 而cos(π)的结果是-1,cos(2π)的结果是1
    // 所以该值除以2加上0.5后,getInterpolation()方法最终返回的结果值还是在0到1之间。只不过经过了余弦运算之后,最终的结果不再是匀速增加的了,而是经历了一个先加速后减速的过程
    // 所以最终,fraction值 = 运算后的值 = 先加速后减速
    // 所以该差值器是先加速再减速的
  • 定义SpringInterpolator(弹簧效果)

public class SpringInterpolator implements Interpolator {
    private static final float factor = 0.2f;
    private float mFactor;

    public SpringInterpolator(float factor) {
        this.mFactor = factor;
    }

    public SpringInterpolator() {
        this(factor);
    }

    @Override
    public float getInterpolation(float input) {
//        factor = 0.1
//        pow(2, -10 * x) * sin((x - factor / 4) * (2 * PI) / factor) + 1
        float out = (float) (Math.pow(2, -10 * input) * Math.sin((input - mFactor / 4) * (2 * Math.PI) / mFactor) + 1);
        if(mListener!=null){
            mListener.onInterpolationChange(input,out);
        }
        return out;
    }

    public interface onInterpolationChangeListener
    {
        void onInterpolationChange(float y, float t);
    }

    onInterpolationChangeListener mListener = null;

    public void setOnInterpolationListener(onInterpolationChangeListener listener){
        mListener = listener;
    }
}
到这里一个自定义的Interpolator就完成了,主要的难点就在公式计算了,分享一个可视化插值器的网站,其中内置了一些插值器公式,还可以查看动画演示效果
Interpolator:http://inloop.github.io/interpolator/

七、应用场景

7-1 标准的动画效果
  • 补间动画常用于视图View的一些标准动画效果:平移、旋转、缩放 & 透明度
7-2 特殊的应用场景
  • Activity 的切换效果
Activity启动动画(自定义左右滑动效果)
  • 先了解一下Activity 的信息位置 如下图


    944365-c5bc4784f2ba9764.png

    通过上图分析进行定义activity进入和退出动画

需要定义四个动画,两个activity的进入和退出动画
 <translate
        android:duration="500"
        android:fromXDelta="100%p"
        android:toXDelta="0%p" />
 <translate
        android:duration="500"
        android:fromXDelta="0%p"
        android:toXDelta="-100%p" />
<translate
        android:duration="500"
        android:fromXDelta="-100%p"
        android:toXDelta="0%p" />
<translate
        android:duration="500"
        android:fromXDelta="0%p"
        android:toXDelta="100%p"/>
使用方法

 startActivity(new Intent(TweenActivity.this, InterpolatorActivity.class));
  overridePendingTransition(R.anim.activity_start_in_animation,R.anim.activity_start_out_animation);

 @Override
    public void finish() {
        super.finish();
        overridePendingTransition(R.anim.activity_finish_in_animation, R.anim.activity_finish_out_animation);
    }

相关文章

  • Android 动画小结 (ViewAnimation-> Tw

    Android 动画 小结 a.视图动画(ViewAnimation)= Tween Animation(补间动画...

  • Android 动画系列一 视图动画(ViewAnimation

    一、概述 Android3.0以前的原生动画视图动画,也叫Tween(补间)动画可以在一个视图容器内执行一系列简单...

  • Android视图动画集合AndoridViewAnimatio

    Android视图动画集合AndoridViewAnimations Android视图动画是针对视图对象的动画效...

  • Android面试Android基础(十二)

    问:Android中动画有哪几种? 答:Android动画可以分为 视图动画 和 属性动画,视图动画又可以分为 补...

  • Android动画之视图动画

    分类 Android动画主要包括视图动画和属性动画。视图动画包括Tween动画和Frame动画。Tween动画又包...

  • Android属性动画

    1. 什么是Android属性动画? Android动画分为视图动画(View 动画)、帧动画(Frame 动画、...

  • Android 动画 | 艺术探索笔记

    Android 动画分为两大类 视图动画 属性动画 视图动画(View animation) 视图动画分为 补间动...

  • Android动画

    Android动画分类: 视图动画:补间动画、逐帧动画 属性动画 视图动画 补间动画 可以在xml中定义动画,然后...

  • Android 动画

    android动画分为三种 帧动画,视图动画(补间动画),属性动画逐帧动画 视图动画 属性动画 Window和A...

  • Android 动画解析

    Android 的动画分类: View视图动画(补间动画 / 逐帧动画) 属性动画Android 动画 0x01 ...

网友评论

      本文标题:Android 动画系列一 视图动画(ViewAnimation

      本文链接:https://www.haomeiwen.com/subject/uevgwftx.html