android开发艺术(五)之Animation(动画)

1. animation简述

Android动画分为三种:view动画、帧动画和属性动画,帧动画也属于View动画的一种,不过它和平移、旋转等常见的view动画在表现形式上略有不同;
View动画通过对场景里的对象不断做图像变换(平移、缩放、旋转、透明度)从而产生动画效果,是一种渐进式动画,并且view动画支持自定义
帧动画通过顺序播放一系列图像从而产生动画效果,可以理解为图片切换动画,如果图片过多过大就会导致OOM
属性动画通过动态的改变对象的属性从而达到动画效果,属性动画为API11新特性,低版本通过兼容库来使用它

2. View动画

View动画的作用对象是View, 它支持4种动画效果,分别是平移动画、缩放动画、旋转动画和透明度动画。除了这四种典型的变换效果外,帧动画也属于View动画,但是帧动画的表现形式和上面的四种变换效果不太一样。

2.1 View动画的种类

四种动画既可以通过xml来定义(可读性好),也可以通过代码来动态创建
在这里插入图片描述
动画描述文件:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    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"
        android:pivotY="float"/>    
     <rotate
        android:fromDegrees="float"
        android:toDegrees="float"
        android:pivotY="float"
        android:pivotX="float"/>
    <alpha 
        android:fromAlpha="float"
        android:toAlpha="float"/>
</set>

< set>标签表示动画集合,对应AnimationSet类,它可以包含若干个动画,并且它的内部也是可以嵌套其他动画集合的,属性的含义如下:
android:interpolator表示动画集合所采用的插值器,插值器影响动画的速度,比如非匀速动画就需要通过插值器来控制动画的播放过程。这个属性可以不指定,默认为@androidanin/accelerate_decelerate_interpolator, 即加速减速插值器
android:shareInterpolator表示集合中的动画是否和集合共享同一个插值器。如果集合不指定插值器,那么子动画就需要单独指定所需的插值器或者使用默认值。
android:duration 动画的持续时间
android:fillafter 动画结束之后view是否停留在结束位置 true表示view停留
android:zAdjustment:允许在动画播放期间,调整播放内容在Z轴方向的顺序
①normal (0): 正在播放的动画内容保持当前的Z轴顺序
②top (1): 在动画播放期间,强制把当前播放的内容放到其他内容的上面
③bottom (-1): 在动画播放期间,强制把当前播放的内容放到其他内容之下

< translate>:表示平移动画,对应TranslateAnimation类。

android:fromXDelta:动画起始时X坐标上的位置。
android:toXDelta:动画结束时X坐标上的位置。
android:fromYDelta:动画起始时Y坐标上的位置。
android:toYDelta:动画结束时Y坐标上的位置。

< scale>:表示缩放动画,对应ScaleAnimation类。

android:fromXScale动画起始时X坐标上的伸缩尺寸。
android:toXScale:动画结束时X坐标上的伸缩尺寸 。
android:fromYScale:动画起始时Y坐标上的伸缩尺寸。
android:toYScale:属性为动画结束时Y坐标上的伸缩尺寸。
android:pivotX:动画相对于物件的X坐标的开始位置。
android:pivotY:动画相对于物件的Y坐标的开始位置。

前四个属性值的值含义

  • 值=0.0 :表示收缩到没有
  • 值<1.0 :表示收缩
  • 值=1.0 :表示无伸缩
  • 值>1.0 :表示放大

后两个属性值表示缩放的轴点:从0%-100%中取值。

< rotate>:表示旋转动画,对应RotateAnimation类。

android:fromDegrees:动画起始时物件的角度 。
android:toDegrees:动画结束时物件旋转的角度。

以上两个属性共同确定旋转方向,原则是:当角度为负数时表示逆时针旋转,反之。故共存在以下四种情况:

  • from=负数->to=正数:表示顺时针旋转
  • from=负数->to=负数:表示逆时针旋转
  • from=正数->to=正数:表示顺时针旋转
  • from=正数->to=负数:表示逆时针旋转
android:pivotY:动画相对于物件的X坐标的开始位置。
android:pivotX:动画相对于物件的Y坐标的开始位置。

以上两个属性值表示旋转的轴点:从0%-100%中取值。

< alpha>:表示透明度动画,对应AlphaAnimation类。

android:fromAlpha:动画起始时透明度。
android:toAlpha动画结束时透明度。

以上两个属性值:从0-1中取值。

  • 值=0.0 :表示完全透明
  • 值=1.0 :表示完全不透明

使用步骤:
1.通过xml文件定义动画 或 代码定义动画
2.设置一个view
3.为view加载这个动画

Button button1= (Button)findViewById(R. id. buttonI) ;
Animation animation=Animat ionUtils.loadAnimatior(this, R.anim.animation_test) : 
buttonl.startAnimation(animation) ;

Button button1= (Button)findViewById(R.id.buttonI) ;
AlphaAnimation alphaAnimation=new AlphaAnimation(O, 1) ;
alphaAnimation.setDuration(3000) ;
buttonl.startAnimation(alphaAnimation) ;

4.同时对于动画时间,android也提供了开始、结束和重复时间的监听方法

public static interface AnimationListener {
        //动画开始        
        void onAnimationStart(Animator animation);
        //动画结束
        void onAnimationEnd(Animator animation);
        //动画重复
        void onAnimationRepeat(Animator animation);
    }

2.2 自定义View动画

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

2.3 View动画的特殊使用场景

1.布局动画LayoutAnimation
作用于ViewGroup,为ViewGroup指定一个动画,当它的子元素出场时都具有该动画效果
(1) 定义LayoutAnimation
在这里插入图片描述
(2) 为元素指定具体的入场动画 anim_item.xml
在这里插入图片描述
(3) 为ViewGroup指定android:layoutAnimation属性
在这里插入图片描述
2.activity的切换效果
Activity有默认的切换效果,但是这个效果我们是可以自定义的,主要用到
overridePendingTransition(int enterAnim, int exitAnim)这个方法,这个方法必须在startActivity(Intent)或者finish()之后被调用才能生效,它的参数含义如下:

enterAnim----Activity被打开时,所需的动画资源id;
exitAnim----Activity被暂停时,所需的动画资源id.

启动活动时:
在这里插入图片描述
结束活动时:
在这里插入图片描述

3. 帧动画

帧动画是顺序播放一组通过xml预先定义好的图片,类似于电影播放。不同于View动画,系统提供了另外一个类AnimationDrawable来使用帧动画。
在这里插入图片描述

4. 属性动画

使用属性动画的前提:
开源动画库:http://nineoldandroids.com/
导入开源动画库implementation 'com.nineoldandroids:library:2.4.0'
在这里插入图片描述

4.1 插值器和估值器

TimeInterpolator 时间插值器

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

TypeEvaluator类型估值器

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

4.2 属性动画的工作原理

在一定时间间隔内,通过不断对值进行改变,并不断将该值赋给对象的属性,从而实现该对象在该属性上的动画效果,get方法和set方法都是通过反射来调用的
step1:创建属性动画时,若未设置属性的初始值,则系统会通过该属性的get()方法获取初始值。故属性动画要求必须提供属性的get()方法。
step2: 在动画播放的过程中,利用时间插值器和类型估值器获取改变后的属性值。
step3:将改变后的属性值通过set()方法设置到对象中。故属性动画要求必须提供属性的set()方法。

4.3 属性动画的实现方式

在res/animator/下可创建属性动画的xml文件。其中,根节点<set>对应AnimatorSet类,子节点<objectAnimator>对应ObjectAnimator类、<animator>对应ValueAnimator类。常用属性:

<set
  android:ordering=["together" | "sequentially"]>

    <objectAnimator
        android:propertyName="string"
        android:duration="int"
        android:valueFrom="float | int | color"
        android:valueTo="float | int | color"
        android:startOffset="int"
        android:repeatCount="int"
        android:repeatMode=["repeat" | "reverse"]
        android:valueType=["intType" | "floatType"]/>

    <animator
        android:duration="int"
        android:valueFrom="float | int | color"
        android:valueTo="float | int | color"
        android:startOffset="int"
        android:repeatCount="int"
        android:repeatMode=["repeat" | "reverse"]
        android:valueType=["intType" | "floatType"]/>

    <set>
        ...
    </set>
</set>

android:ordering:设置动画的时序关系。可选值:
together:默认值。表示动画集合中的子动画同时播放。
sequentially:表示动画集合中的子动画按照书写的先后顺序依次播放。

1.通过ObjectAnimator实现属性动画

  • 原理:通过直接对对象(object)的属性值进行改变操作,从而实现动画效果
  • 常用属性:
    android:propertyName:属性动画作用的属性名称。
    android:duration: 动画持续时长。
    android:startOffset:设置动画执行之前的等待时长。
    android:repeatCount:动画重复执行的次数。
    默认为0,表示只播放一次;设置为-1或infinite,表示无限重复。
    android:repeatMode:动画重复执行的模式。可选值:
    restart:表示连续重复,为默认值;reverse :表示逆向重复。
    android:valueFrom:动画初始值。
    android:valueTo:动画结束值。
    android:valueType:动画值类型。可选值:
    intType :以上两个value属性值为整型。
    floatType:即以上两个value属性值为浮点型,为默认值。
    若为color值,则无需设置该属性。

2.通过ValueAnimator实现属性动画

  • 原理:通过不断控制值(value)的变化,再不断手动赋给对象的属性,从而实现动画效果。
  • ObjectAnimator与 ValueAnimator类的区别:
    ValueAnimator 类是先改变值,然后手动赋值给对象的属性从而实现动画;是间接对对象属性进行操作;
    ObjectAnimator 类是先改变值,然后自动赋值给对象的属性从而实现动画;是直接对对象属性进行操作;
  • 对应根节点<animator>常用属性比标签少一个android:propertyName属性,其他相同。

4.4 属性动画的监听器

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

AnimatorListener :监听动画的开始、结束、取消以及重复播放。如下:

public static interface AnimatorListener {
    void onAnimationStart(Animator animation); //动画开始
    void onAnimationEnd(Animator animation); //动画结束
    void onAnimationCancel(Animator animation); //动画取消
    void onAnimationRepeat(Animator animation); //动画重复播放
}

AnimatorListener可以监听动画的开始、结束、取消以及重复播放。同时为了方便开发,系统还提供了AnimatorListenerAdapter 这个类,它是AnimatorListener的适配器类,这样我们就可以有选择地实现上面的4个方法了

AnimatorUpdateListener :监听整个动画过程。动画是由许多帧组成的,每播放一帧,onAnimationUpdate 就会被调用一次

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

5. 动画相关问题

set方法无法对UI进行修改

针对部分View的set方法对属性的改变没有带来UI的改变,提出三种解决方案:

  1. 给对象加上get和set方法(在有权限的前提下)
  2. 使用ViewWrapper等包装类对原始View对象进行包装,间接提供get和set方法;在set方法中对属性进行动画设置
private void performAnimate() (
	ViewWrapper wrapper = new ViewWrapper (mButton);
	objectAnimator.ofInt(wrapper, "width", 500).setDuration(5000).start();
@Override
public void onClick(View v) (
	if (v==mButton)
		performAnimate() ;
}
private static class ViewWrapper {
	private Vlev mTarget:
	public Viewrapper(View target) {
		mTarget = target;}
	public int getwidth() {
		return mTarget.getLayoutParams().width;}
	public void setWidth(int width) {
		mTarget.getLayoutParams().width = width;
		mTarget.requestLayout();
}
  1. 采用ValueAnimator,监听动画过程,自己实现属性的改变
    在这里插入图片描述

注意事项

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值