安卓开发艺术笔记 | 动画解析(View动画,帧动画,属性动画)

 

一.VIEW动画

  1. view动画的种类

  2. 自定义view动画

  3. view动画的特殊类型

二.帧动画

三.属性动画

  1. 属性动画的分类
  2. 和View动画的区别
  3. 插值器与估值器
  4. 属性动画的使用
  5. 属性动画的监听器
  6. 属性动画工作原理
  7. 属性动画的注意事项

四.动画注意事项

 

一.View动画

1.view动画种类

(1)分类

安卓开发艺术笔记 | 动画解析(View动画,帧动画,属性动画)_第1张图片

注意:view动画不改变View的属性,点击事件等任在原位置响应。

 

(2)view动画的实现(推荐使用xml文件实现)

实现方法1:xml文件实现,activity引用

xml文件(路径为res/anim)

 
 //动画完成后是否停留在结束位置
    
   
     
    

 java中引用

Animation animation = AnimationUtils.loadAnimation(this, R.anim.XXX);
mView.startAnimation(animation);

实现方法二:java代码创建

设置对应动画的参数,构造对象,再调用即可

AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
    alphaAnimation.setDuration(2000);
    mImageView.startAnimation(alphaAnimation);

 

2.自定义View动画

四种动画不能满足需要,自定义动画。

步骤:继承Animation->重写initialize()applyTransformation()方法:initialize()用于初始化;applyTransformation()用于进行矩阵变换

 

3.View动画的特殊类型

(1)LayoutAnimation

  • 作用于ViewGroup,为ViewGroup制定一个动画,这样当他的子元素出场时就会有设置的动画效果,可用于ListView等

实现方法一:通过xml文件实现,布局.xml文件中引用

res/anim/anim_layout.xml

//子元素动画的播放顺序:
                   //normal (正常顺序)、random(随机顺序)、reverse(倒序)。
 

res/anim/anim_item.xml

 
 
    
    

布局文件中引用(假设为ListView)

 

实现方法2:java代码创建

Animation animation = AnimationUtils.loadLayoutAnimation(this, R.anim.anim_item);
LayoutAnimationController controller = new LayoutAnimationController(animation);//对应android:animation属性
controller.setDelay(0.5);//对应android:delay属性       
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);//对应android:animationOrder属性
listView.setLayoutAnimation(controller);//对应android:layoutAnimation属性

 

(2)Activity的切换效果

  • 该文件创建在res/anim/下
  • Activity默认是有切换效 果的,若需要自定义切换效果,需要用到overridePendingTransition(int inAnim, int outAnim)方法。
  • 该方法调用在startActivity()或finish()之后才生效。
startActivity(intent);
//(进入动画.xml,退出动画.xml)
overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim);

二.逐帧动画

1.定义:

帧动画也是View动画的一种,它会按照顺序播放一组预先定义好的图片。对应类AnimationDrawable

注意:逐帧动画不能使用尺寸过大的图片,否则会造成OOM

 

2.逐帧动画的实现

方法一:xml定义(位于res/drawable/下),java代码中作为view的背景引入

xml文件

 
//是否执行一次
    //持续时间
     
    
    

activity

mView.setBackgroundResource(R.drawable.XXX); 
AnimationDrawable animationDrawable = (AnimationDrawable)mView.getBackground(); 
animationDrawable.start();

 

方法二:java代码动态创建

//和上述xml定义方法的效果相同
AnimationDrawable ad = new AnimationDrawable();//1.创建AnimationDrawable对象
    for (int i = 0; i < 4; i++) {//2.添加Drawable对象及其持续时间
        Drawable drawable = getResources().getDrawable(getResources().getIdentifier("xxx" + i, "drawable", getPackageName()));
        ad.addFrame(drawable, 500);
    }
ad.setOneShot(false);//3.设置是否执行一次
mView.setBackgroundResource(ad);//4.将帧动画作为view背景
ad.start();//5.播放动画

三.属性动画

1.属性动画分类

根节点对应AnimatorSet

对应ObjectAnimator类

对应ValueAnimator

两个子节点区别:

  • ValueAnimator 类是先改变值,然后手动赋值给对象的属性从而实现动画;是间接对对象属性进行操作;(手动赋值的过程通过监听动画,然后改变对象属性,重绘来实现,需要自己实现)
  • ObjectAnimator 类是先改变值,然后自动赋值给对象的属性从而实现动画;是直接对对象属性进行操作

 

2.和View动画的区别

安卓开发艺术笔记 | 动画解析(View动画,帧动画,属性动画)_第2张图片

 

3.插值器与估值器

1)插值器

  • 作用:根据时间流逝的百分比计算出当前属性值改变的百分比。确定了动画效果变化的模式,如匀速变化、加速变化等等。
  • 常用的系统内置插值器:
  1. 线性插值器(LinearInterpolator):匀速动画
  2. 加速减速插值器(AccelerateDecelerateInterpolator):动画两头慢中间快
  3. 减速插值器(DecelerateInterpolator):动画越来越慢
  • 可针对的对象
  1. View动画:插值器对应的属性是android:interpolator。
  2. 属性动画:是实现非匀速动画的重要手段。
  • 自定义插值器方法:实现 Interpolator (view动画)/ TimeInterpolator(属性动画)接口 ,然后复写getInterpolation()。

 

(2)估值器(TypeEvaluator)

  • 作用:根据当前属性改变的百分比计算出改变后的属性值
  • 常用的系统内置的估值器:
    1. 整形估值器(IntEvaluator)
    2. 浮点型估值器(FloatEvaluator)
    3. Color属性估值器(ArgbEvaluator)
  • 针对于属性动画,View动画不需要类型估值器。是属性动画实现非匀速动画的重要手段。
  • 自定义估值器方法:实现TypeEvaluator接口,然后复写evaluate()

 

4.属性动画的实现

(1)xml中实现(位于res/animator/),java中引用

res/animator/propertyName.xml(ValueAnimator)

// ObjectAnimator 采用  标签
  

java代码中引用

Animator animator = AnimatorInflater.loadAnimator(context, R.animator.propertyName);  
// 载入XML动画
animator.setTarget(view);  
// 设置动画对象
animator.start();  
// 启动动画

 

(2)java代码动态生成

ObjectAnimator animator = ObjectAnimator.ofFloat(Object object, String property, float ....values);  

// ofFloat()作用有两个
// 1. 创建动画实例
// 2. 参数设置:参数说明如下
// Object object:需要操作的对象
// String property:需要操作的对象的属性
// float ....values:动画初始值 & 结束值(不固定长度)
// 若是两个参数a,b,则动画效果则是从属性的a值到b值
// 若是三个参数a,b,c,则则动画效果则是从属性的a值到b值再到c值
// 以此类推
// 至于如何从初始值 过渡到 结束值,同样是由估值器决定,此处ObjectAnimator.ofFloat()是有系统内置的浮点型估值器FloatEvaluator,同ValueAnimator讲解

anim.setDuration(500);
        // 设置动画运行的时长

        anim.setStartDelay(500);
        // 设置动画延迟播放时间

        anim.setRepeatCount(0);
        // 设置动画重复播放次数 = 重放次数+1
        // 动画播放次数 = infinite时,动画无限重复

        anim.setRepeatMode(ValueAnimator.RESTART);
        // 设置重复播放动画模式
        // ValueAnimator.RESTART(默认):正序重放
        // ValueAnimator.REVERSE:倒序回放

animator.start();  
// 启动动画

 

5.属性动画的监听器

属性动画主要使用两个接口:AnimatorUpdateListener&AnimatorListener来监听动画的播放过程。

  • AnimatorListener :监听动画的开始、结束、取消以及重复播放。
  • 为方便开发,系统提供了AnimatorListenerAdapter类,它是AnimatorListener的适配器,如此可有选择复写上述四个方法。
  • AnimatorUpdateListener :监听整个动画过程。每播放一帧onAnimationUpdate()就会被调用一次
public static interface AnimatorListener {
    void onAnimationStart(Animator animation); //动画开始
    void onAnimationEnd(Animator animation); //动画结束
    void onAnimationCancel(Animator animation); //动画取消
    void onAnimationRepeat(Animator animation); //动画重复播放
}

public interface AnimatorUpdateListener {
  void onAnimationUpdate(ValueAnimator var1);//在属性动画的属性值变化是回调。
}

 

6.属性动画的工作原理

在一定时间间隔内,通过不断对值进行改变,并不断将该值赋给对象的属性,从而实现该对象在该属性上的动画效果。(通过反射调用get/set方法)

  • step1:创建属性动画时,若未设置属性的初始值,则系统会通过该属性的get()方法获取初始值。故属性动画要求必须提供属性的get()方法。
  • step2: 在动画播放的过程中,利用时间插值器和类型估值器获取改变后的属性值。
  • step3:将改变后的属性值通过set()方法设置到对象中。故属性动画要求必须提供属性的set()方法。

 

7.属性动画注意事项

由于需要调用对象的get/set方法来动态改变对象的属性,所以对objec的abc属性做动画,想要让动画生效必须满足两个条件:

  1. object必须提供setABC方法,如果动画的时候没有传递初始值,那么还要提供getABC方法,系统会通过该属性的get()方法获取初始值(如果这条不满足,程序直接crash
  2. obje的setABC对属性abc做出的改变必须能够以某种方式反映出来,比如UI变化(这条不满足,不会crash但是动画没有效果)

 

例子:

对Button的的width属性做动画,没有相应效果(可以验证)。

原因:Button的setWidth是继承自TextView的方法,设置的是TextView的最大宽度,不是设置View的宽,不满足第二条。

解决办法:

  • 给你的对象加上get/set方法(Android SDK内部实现,所以这个方法无效)
  • 用一个类包装原始对象,间接为其提供get和set方法
  • 采用ValueAnimator,监听动画过程,自己实现属性的改变

 

(2)用一个类包装原始对象,间接为其提供get和set方法

private void performAnimate() {
        ViewWrapper viewWrapper = new ViewWrapper(btn);
        ObjectAnimator.ofInt(viewWrapper, "width", 500).setDuration(1000).start();
    }

    private static class ViewWrapper {

        private View mTarget;

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

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

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

 

(3)采用ValueAnimator

  private void performAnimator(final View target, final int start, final int end) {
        ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            //持有一个IntEvaluator对象,方便下面估值的时候使用
            private IntEvaluator mEvaluator = new IntEvaluator();

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //获得当前动画的进度值,整形1-100之间
                int currentValue = (int) animation.getAnimatedValue();
                //获得当前进度占整个动画之间的比例,浮点0-1之间
                float fraction = animation.getAnimatedFraction();
                //直接使用整形估值器,通过比例计算宽度,然后再设置给按钮
                target.getLayoutParams().width = mEvaluator.evaluate(fraction, start, end);
                target.requestLayout();
            }
        });
        valueAnimator.setDuration(5000).start();
    }

四.动画注意事项

  • 1.OOM问题

这个问题主要还是帧动画中,当图片过多的时候就OOM了,这个在实际的开发中尤其注意,尽量避免使用帧动画

  • 2.内存泄漏

在属性动画中有一类无限循环的动画,如果你在activity退出后不停止的话,可能就会存在这个问题了

  • 3.兼容性问题

动画在3.0以下的系统上有缺陷,最好做好适配工作

  • 4.View动画的问题

view动画死对view的影像做动画,并不是真正的改变view的状态,因此有时候会出现完成后view无法隐藏的现象,即setVisibility(View.GONE),这个时候只要调用clearAnimation清除动画即可

  • 5.不要使用PX

在进行动画的过程,要尽量使用dp,使用px会导致适配问题

  • 6.动画元素的交互

将view移动后,在3.0以前的系统,不管是view动画还是属性动画,新位置都无法调用单机事件,同时老位置却可以,从3.0之后,属性动画的点击事件触发位置为移动后的位置,但是view动画仍然在原位置。

  • 7.硬件加速

使用动画的过程,建议开启硬件加速,这样会提高动画的流畅性 动画

 

你可能感兴趣的:(安卓开发)