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

 

一.VIEW动画

  1. view动画的种类

  2. 自定义view动画

  3. view动画的特殊类型

二.帧动画

三.属性动画

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

四.动画注意事项

 

一.View动画

1.view动画种类

(1)分类

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

 

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

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

xml文件(路径为res/anim)

<?xml version="1.0" encoding="utf-8"?> 
<set  //动画集合
     xmlns:android="http://schemas.android.com/apk/res/android" 
     android:interpolator="your interpolator"//插值器,系统有默认值,详见后面
     android:shareInterpolator="true" //集合的动画是否和动画共享一个插值器
     android:fillAfter="true"> //动画完成后是否停留在结束位置
   <translate  //平移
     android:fromXDelta="float" 
     android:toXDelta="float" 
     android:fromYDelta="float" 
    android:toYDelta="float"/> 
   <scale  //缩放
    android:fromXScale="float" 
    android:toXScale="float"
    android:fromYScale="float" 
    android:toYScale="float" 
    android:pivotX="float"  //旋转的中心点x,默认为元素中心
    android:pivotY="float"/>
    <rotate   //旋转
    android:fromDegrees="float" 
    android:toDegrees="float"
    android:pivotY="float" //缩放中心点
    android:pivotX="float"/> 
    <alpha 
    android:fromAlpha="float" 
    android:toAlpha="float"/>
</set>

 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

<layoutAnimation 
   xmlns:android="http://schemas.android.com/apk/res/android" 
   android:animation="@anim/anim_item" //指定具体动画
   android:delay="0.5" 
   android:animationOrder="normal">//子元素动画的播放顺序:
                   //normal (正常顺序)、random(随机顺序)、reverse(倒序)。
 </layoutAnimation>

res/anim/anim_item.xml

<?xml version="1.0" encoding="utf-8"?> 
<set  //动画集合
     xmlns:android="http://schemas.android.com/apk/res/android" 
     android:interpolator="@android:anim/accelerate_interpolator"
     android:shareInterpolator="true"> 
   <translate  //平移
     android:fromXDelta="111" 
     android:toXDelta="0" /> 
    <alpha 
    android:fromAlpha="0" 
    android:toAlpha="1"/>
</set>

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

<ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layoutAnimation="@anim/anim_layout"/>

 

实现方法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文件

<?xml version="1.0" encoding="utf-8"?> 
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" 
   android:oneshot="false">//是否执行一次
    <item 
    android:drawable="@drawable/xxx1" //图片源
    android:duration="500"/>//持续时间
    <item 
    android:drawable="@drawable/xxx2" 
    android:duration="500"/> 
   <item 
   android:drawable="@drawable/xxx3" 
   android:duration="500"/> 
   <item 
   android:drawable="@drawable/xxx4" 
   android:duration="500"/> 
</animation-list>

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.属性动画分类

根节点<set>对应AnimatorSet

点<objectAnimator>对应ObjectAnimator类

<animator>对应ValueAnimator

两个子节点区别:

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

 

2.和View动画的区别

 

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 采用<animator>  标签
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"  
    android:valueFrom="1"   // 初始值
    android:valueTo="0"  // 结束值
    android:valueType="floatType"  // 变化值类型 :floatType & intType
    android:propertyName="alpha" // 对象变化的属性名称
/>  

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.硬件加速

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值