Android 动画深入分析(一)——逐帧动画,补间动画

文章目录

一.前言

Android的动画大致分为三种 ,分别是 逐帧动画 ,补间动画 ,属性动画

二.逐帧动画

逐帧动画的工作原理很简单,其实就是将一个完整的动画拆分成一张张单独的图片,然后再将它们连贯起来进行播放,类似于动画片的工作原理。
 
步骤:

  1. 在res/drawable目录下定义一个XML文件,根节点为系统提供的animation-list,然后放入定义更好的图片;
  2. 使用AnimationDrawable类播放第一步定义好的Drawable中的图片,形成动画效果;

示例代码,第一步,创建Drawable文件:

<?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/image1" android:duration="500"/>
    <item android:drawable="@drawable/image2" android:duration="500"/>
    <item android:drawable="@drawable/image3" android:duration="500"/>

</animation-list>

说明:

  • android:oneshot=“false”: 表示是否重复播放动画,还是只播放一次;
  • 每个item都有Drawable和duration属性,Drawable表示我们要播放的图片;duration表示这张图播放的时间;

示例代码,第二步,用AnimationDrawable播放动画:

 button = findViewById(R.id.button);
 button.setBackgroundResource(R.drawable.frame_animation);//把Drawable设置为button的背景
 AnimationDrawable drawable = (AnimationDrawable) button.getBackground();//拿到这个我们定义的Drawable,实际也就是AnimationDrawable
drawable.start();//开启动画

**注意:**在使用帧动画是应该尽量避免使用过多尺寸较大的图片,否则容易引起OOM
 

三.补间动画

补间动画的介绍

我们只需要拿到一个view,设定它开始和结束的位置,中间的view会自动由系统补齐,而不需要帧动画每一幅图都是提前准备好的。
 
补间动画是Android一开始就提供的比较原始的动画,主要支持四种效果:平移、缩放、旋转、透明度变化(渐变) 四种基本效果,我们可以再这四种基础效果的基础上,选择其中的几种进行组合。
 
View动画的四种基本效果对应了四个Animation的子类,如下:
Android 动画深入分析(一)——逐帧动画,补间动画

补间动画的使用

单个使用

 
第一步创建动画的xml文件
 

  1. 平移动画(需要把xml文件放在res/anim目录)
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="100"  	//水平开始点的坐标
    android:fromYDelta="0"
    android:toXDelta="0"		//水平结束点的坐标		
    android:toYDelta="0"/>
  1. 缩放动画
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"			//动画的时间间隔
    android:fromXScale="0.0"		//水平缩放的起始值
    android:fromYScale="0.0"
    android:pivotX="50%"			//pivotX和pivotY表示以缩放中心的位置。
    android:pivotY="50%"
    android:toXScale="1.0"			//水平方向缩放的结束值
    android:toYScale="1.0"/>

  1. 旋转动画
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
      android:fromDegree="0"	//开始旋转的角度
      android:toDegree="1800"	//
      android:pivotX = "50%"
      android:pivotY="50%"
      android:duration = "3000"
/>
  1. 渐变动画
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"		//动画的持续时间
    android:fromAlpha="1.0"		//透明度的起始值
   	android:fillAfter = true	//动画结束之后View是否停留在结束位置
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:toAlpha="0.0" 		//透明度的结束值
    />

注意点:
interpolator表示动画插值器, 可以控制动画的变化速率, 比如前200ms很慢,中间600ms很快,最后200ms又很慢。
 
pivot 这个属性主要是在translate 和 scale 动画中,这两种动画都牵扯到view 的“物理位置“发生变化,所以需要一个参考点。 而pivotX和pivotY就共同决定了这个点;它的值可以是float或者是百分比数值。
以 pivotX 为例,说明其取不同的值的含义:

  • 10:距离动画所在view自身左边缘10像素
  • 10% :距离动画所在view自身左边缘 的距离是整个view宽度的10%
  • 10%p:距离动画所在view父控件左边缘的距离是整个view宽度的10%

** 第二步,使用**

 Animation animation = AnimationUtils.loadAnimation(this, R.anim.filename);
textView.startAnimation(animation);

** 也可用代码完成不借助xml文件**

	AlphaAnimation alphaAnimation = new AlphaAnimation(0,1);
            alphaAnimation.setDuration(2000);
            //设置动画的监听
            alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {

                }

                @Override
                public void onAnimationEnd(Animation animation) {
                     Animation animation1= AnimationUtils.loadAnimation(MainActivity.this, R.anim.filename);
                     textView.startAnimation(animation1);

                }

                @Override
                public void onAnimationRepeat(Animation animation) {

                }
            });
            textView.startAnimation(alphaAnimation);

嵌套使用

我们可以使用AnimationSet把View动画的平移、缩放、旋转、渐变都揉在一起,也是既能通过代码实现,也可以通过xml实现
xml实现:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
 android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    >
    <scale
        android:duration="3000"
        android:fromXScale="0.0"
        android:fromYScale="0.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="1.0"
        android:toYScale="1.0"/>
    <alpha
        android:duration="3000"
        android:fromAlpha="1.0"
        android:toAlpha="0.5" />
    <rotate
        android:fromDegrees="0"
        android:toDegrees="720"
        android:pivotX = "50%"
        android:pivotY="50%"
        android:duration = "3000"
        />
    <translate
        android:fromXDelta="0"
        android:toXDelta="100"
        android:fromYDelta="0"
        android:toYDelta="100" />
</set>

代码实现:

AnimationSet setAnimation = new AnimationSet(true);
    // 特别说明以下情况
    // 因为在下面的旋转动画设置了无限循环(RepeatCount = INFINITE)
    // 所以动画不会结束,而是无限循环
    // 所以组合动画的下面两行设置是无效的, 以后设置的为准
    setAnimation.setRepeatMode(Animation.RESTART);
    setAnimation.setRepeatCount(1);// 设置了循环一次,但无效

    // 旋转动画
    Animation rotate = new RotateAnimation(0,360,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
    rotate.setDuration(1000);
    rotate.setRepeatMode(Animation.RESTART);
    rotate.setRepeatCount(Animation.INFINITE);

    // 平移动画
    Animation translate = new TranslateAnimation(TranslateAnimation.RELATIVE_TO_PARENT,-0.5f,
            TranslateAnimation.RELATIVE_TO_PARENT,0.5f,
            TranslateAnimation.RELATIVE_TO_SELF,0
            ,TranslateAnimation.RELATIVE_TO_SELF,0);
    translate.setDuration(10000);

    // 透明度动画
    Animation alpha = new AlphaAnimation(1,0);
    alpha.setDuration(3000);
    alpha.setStartOffset(7000);

    // 缩放动画
    Animation scale1 = new ScaleAnimation(1,0.5f,1,0.5f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
    scale1.setDuration(1000);
    scale1.setStartOffset(4000);

    // 将创建的子动画添加到组合动画里
    setAnimation.addAnimation(alpha);
    setAnimation.addAnimation(rotate);
    setAnimation.addAnimation(translate);
    setAnimation.addAnimation(scale1);
    // 使用
    mButton.startAnimation(setAnimation);

View动画的特殊使用场景

1.LayoutAnimation

LayoutAnimation作用于ViewGroup,为ViewGroup指定一个动画,然后,当它的子元素出场时都会具有这种效果。这种效果常被用于ListView,有的ListView的每个item都以一定的动画形式出现,用到的就是LayoutAnimation。
 
使用步骤:

  1. 定义LayoutAnimation的xml文件;
  2. 指定具体的入场动画;
  3. 为ViewGroup指定android:layoutAnimation属性,引用这个LayoutAnimation的xml文件;

第一步: 定义LayoutAnimation的xml文件;

// res/anim/anim_layout.xml
<layoutAnimation
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:delay="0.5"		//每个子元素开始动画的时间延迟
	android:animationOrder="normal"	
	/*
	子元素动画的顺序,有三个值
	normal(顺序显示)
	reverse(逆向显示)
	random(随机播放入场动画)
	*/
	android:animation="@anim/anim_item"/>

第二步: 指定具体的入场动画;

// res/anim/anim_item.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
	android:duration="300"
	android:interpolator="@android:anim/accelerate_interpolator"
	android:shareInterpolator="true" >
	<alpha
	android:fromAlpha="0.0"
	android:toAlpha="1.0" />
	<translate
	android:fromXDelta="500"
	android:toXDelta="0" />
</set>

第三步: 为ViewGroup指定android:layoutAnimation属性;

<ListView
	android:id="@+id/list"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:layoutAnimation="@anim/anim_layout"
	android:background="#fff4f7f9"
	android:cacheColorHint="#00000000"
	android:divider="#dddbdb"
	android:dividerHeight="1.0px"
	android:listSelector="@android:color/transparent" />

单用代码实现:

ListView listView = (ListView) layout.findViewById(R.id.list);
Animation animation = AnimationUtils.loadAnimation(this,R.anim.anim_
item);
LayoutAnimationController controller = new LayoutAnimationController
(animation);
controller.setDelay(0.5f);
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
listView.setLayoutAnimation(controller);

2.Activity的切换效果

Activity有默认的切换效果,但是我们可以定制,主要用到overridePendingTransition(int enterAnima, int exitAnima)这个方法:

当启动一个Activity时

Intent intent = new Intent(this,TestActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);

当Activity退出时:

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

注意:
overridePendingTransition这个方法必须位于startActivity或者finish后面,否则动画会没有效果。
Fragment的切换效果:可以使用FragmentTransaction的setCustomAnimation方法添加切换动画。

四.属性动画

上一篇:CSS动画实例:圆的涟漪扩散


下一篇:【XSTAR原型设计】Bootstrap弹窗效果原型图的快速实现