本文介绍Android动画的相关知识和使用方法:逐帧动画和补间动画。
逐帧动画逐帧动画就是顺序播放事先准备好的静态图像,利用人眼的”视觉暂留”的原理,给用户选择动画的错觉.
1.设计xml文件,要放在在drawable文件夹内
2.创建AnimationDrawable对象
3.使用AnimationDrawable操作动画的开始和暂停
比如:
//实例化控件对象
TextView textView = (TextView) findViewById(R.id.main_text);
//获取动画对象才能对动画进行操作
AnimationDrawable
anim = (AnimationDrawable) textView.getBackground();
//开始动画
anim.start();
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item
android:drawable="@mipmap/img001"
android:duration="200" />
<item
android:drawable="@mipmap/img002"
android:duration="200" />
<item
android:drawable="@mipmap/img003"
android:duration="200" />
<item
android:drawable="@mipmap/img004"
android:duration="200" />
<item
android:drawable="@mipmap/img005"
android:duration="200" />
<item
android:drawable="@mipmap/img006"
android:duration="200" />
animation-list>
这里每一图片的动画时间单位是毫秒,如果设置时间太长,会显示幻灯片的效果,一般设置在100毫秒左右.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.lwz.frameanimation.MainActivity">
<TextView
android:id="@+id/main_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="@drawable/anim_frame"
android:text="动态图" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="start"
android:text="开始动画" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="stop"
android:text="停止动画" />
LinearLayout>
RelativeLayout>
这里的动画属性资源要放在background里面才能使用。
public class MainActivity extends AppCompatActivity {
//布局内的控件
TextView textView;
//控制帧动画的对象
AnimationDrawable anim;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//实例化控件对象
textView = (TextView) findViewById(R.id.main_text);
//获取动画对象才能对动画进行操作
anim = (AnimationDrawable) textView.getBackground();
}
//开始动画
public void start(View v) {
anim.start();
}
//停止动画
public void stop(View v) {
anim.stop();
}
}
这里的动画操作对象是通过getBackground获取的,所以之前的动画资源要放在background里面。如果是ImageView的src放入动画资源是无法取得动画的对象的。
这是一个表情包效果的动画,但是主要应用还是奔跑进行中的动画使用。
补时动画就是通过对场景的对象不断进行图像变化来产生动画效果,在实现补时动画时,只要定义动画开始和结束的”关键帧”其它过度帧由系统自动计算并补齐.android中提供了4种补间动画效果:透明、旋转、缩放、平移;
补间动画也要设置xml资源文件,但是它的资源文件放在anim文件夹里面,这个文件夹需要我们自己创建在res目录下。
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha android:fromAlpha="1"
android:toAlpha="0"
android:repeatMode="reverse"
android:repeatCount="1" 变化次数
android:duration="2000"/>
set>
属性说明
1. android:interpolator
用于控制动画的变化速度,使用动画效果可以匀速,加速,减速或抛物线速度等各种速度变化具体
见下表android:interpolotor属性的常用属性值
2. android:repeatMode
用于设置动画的重复方式,可选择为reverse(反向)或restart(重新开始)
3. android:repeatCount
用于设置动画的重复次数,属性可以是代表次数的数值,也可以是infinite(无限循环)
4. android:duration
用于指定donghua持续的时间,单位为毫秒
5. android:fromAlpha
用于指定动画开始时的透明度,值为0.0代表完全透明 ,值为1.0代表完全不透明
6. android:toAlpha
用于指定动画结束时的透明度,值为0.0代表完全透明,值为1.0代表完全不透明
7.android:interpolator属性的常用属性值
1) @android:anim/linear_interpolator 动画一直在做匀速改变
2) @android:anim/accelerate_interpolator 动画一在开始的地方变较慢,然后开始加
速
3) @android:anim/decelerate_interpolator 在动画开始的地方改变速度较快,然后开
始减速
4)@android:anim/accelerate_decelerate_interpolator 动画在开始和结束的地方
改变速度较慢,在中间的时候加速
5) @android:anim/cycle_interpolator 动画循环播放特定的次数,变化速度按正弦
曲线改变
6)@android:anim/bounce_interpolator 动画结束的地方采用弹球效果
7)@android:anim/anticipate_overshoot_interpolator 在动画开始的地方先向后退一
小步,再开始动画,到结束的地方再超出一小步,最后回到动画结束的地方
8)@android:anim/overshoot_interpolator 动画快速到达终点,并超出一小步最后回到动画结束的地方
9)@android:anim/anticipate_interpolator 在动画开始的地方先向后退一小步,再快速到达动画结束的地方
上面的很多属性值对下面的动画效果也是有效的。
旋转动画就是通过为动画指定开始时的旋转角度,结束时的旋转角度,经及持续时间来创建动画,在旋转时还可以通过指定轴心点坐标来改为旋转的中心
旋转动画的资源文件设计如下:
<set xmlns:android="http://schemas.android.com/apk/res/android">
android:interpolator="@android:anim/accelerate_interpolator"
android:fromDegrees="0"
android:toDegrees="720"
android:pivotX="50%"
android:pivotY="50%"
android:duration="2000">
set>
属性说明
1. android:interpolotor 用于控制动画的变化速度,使用动画效果可以匀速,加速,减速或抛物线速度等各种速度变化具体
见表android:interpolator属性的常用属性值
2. android:fromDegrees 用于指定动画开始时旋转的角度
3. android:toDeggrees 用于指定动画结束时旋转的角度
4. android:pivotX 用于指定轴心点X轴坐标
5. android:pivotY 用于指定轴心点Y轴坐标
6. android:repeatMode 用于设置动画的重复方式,可选择为reverse(反向)或restart(重新开始)
7. android:repeatCount 用于设置动画的重复次数,属性可以是代表次数的数值,也可以是infinite(无限循环)
8. android:duration 用于指定动画持续的时间,单位为毫秒
缩放动画就是通过为动画指定开始时报缩放系数,结束时的缩放系数,以及持续时间来他建动画,在缩放时还可以通过指定轴心点坐标来改变绽放的中心。
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale android:fromXScale="1"
android:interpolator="@android:anim/decelerate_interpolator"
android:fromYScale="1"
android:toXScale="2.0"
android:toYScale="2.0"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="1"
android:repeatMode="reverse"
android:duration="2000"/>
set>
属性说明
1. android:interpolotor 用于控制动画的变化速度,使用动画效果可以匀速,加速,减速或抛物线速度等各种速度变化具体见表android:interpolotor属性的常用属性值
2. android:fromXScale 用于指定动画开始时水平方向上的缩放系数,值为1.0表示不变化
3. android:toXScale 用于指定动画结束时水平方向上的缩放系数,值为1.0表示不变化
4. android:fromYScale 用于指定动画开始时垂直方向上的缩放系数,值为2.0表示放大一倍
5. android:toYScale 用于指定动画结束时垂直方向上的缩放系数,值为2.0表示放大一倍
6. android:pivotX 用于指定轴心点X轴坐标,50%表示自身的x轴中心点的,50%p表示父框体的x轴中心点
7. android:pivotY 用于指定轴心点Y轴坐标,50%表示自身的y轴中心点的,50%p表示父框体的y轴中心点
8. android:repeatMode 用于设置动画的重复方式,可选择为reverse(反向)或restart(重新开始)
9. android:repeatCount 用于设置动画的重复次数,属性可以是代表次数的数值,也可以是infinite(无限循环)
10. android:duration 用于指定动画持续的时间,单位为毫秒
平稳动画就是通过为动画指定开始时的位置,结束时的位置,经及持续时间来创建动画
<set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true"
>
"0"
android:toXDelta="320"
android:fromYDelta="0"
android:toYDelta="0"
android:repeatMode="reverse"
android:repeatCount="1"
android:duration="2000">
set>
属性说明
1. aandroid:fillAfter 用于指定动画结束后是否保存最后的效果,true代表是,这个属相一般要写在根标签里面,写在子标签里面是起不到作用的。
2. android:fromXDelta 用于指定动画开始时水平方向上的起始位置,默认单位是像素,可以使用100%代表的是自身长度,100%p代表的是父框体的长度。下面的距离也可以这样表示。
3. android:toXDelta 用于指定动画结束时水平方向上的起始位置
4. android:fromYDelta 用于指定动画开始时垂直方向上的起始位置
5. android:toYDelta 用于指定动画结束时垂直方向上的起始位置
6. android:repeatMode 用于设置动画的重复方式,可选择为reverse(反向)或restart(重新开始)
7. android:repeatCount 用于设置动画的重复次数,属性可以是代表次数的数值,也可以是infinite(无限循环)
8. android:duration 用于指定动画持续的时间,单位为毫秒
上面就是四种补间动画的资源文件的属性介绍,其中有很多属性的值是相同的,有些也是有区别的,有些值是必须要设置的,比如:动画时间,相关动画效果的起始值和结束值。
注意:持续时间是一次动画的时间,如果设置的动画的次数是2,那么动画结束时花的时间是3倍的动画持续时间。
还有就是,一个set标签里面可以放多个动画效果的标签,比如一个在移动的图片可以让它同时改变透明的,也可以让它同时旋转等等。
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="4000"
android:fromAlpha="1"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:repeatCount="5"
android:fillAfter="true"
android:toAlpha="0" />
这里的透明效果是从开始显示到最后完全消失,执行六次,总共花费时间24秒。最后完全消失!
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="4000"
android:fillAfter="true"
android:fromDegrees="0"
android:toDegrees="1080"
android:pivotX="50%"
android:pivotY="50%"
android:repeatMode="reverse"
android:repeatCount="3"
/>
这里的旋转效果是图片从正常状态开始顺时针旋转三圈,然后反向旋转三圈,顺时针旋转三圈,然后反向旋转三圈,旋转四圈后停止。而且这里的旋转都是以自身的中心点开始旋转的。
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="4000"
android:fillAfter="true"
android:fromXScale="1"
android:fromYScale="1"
android:toXScale="1.5"
android:toYScale="1.5"
android:pivotX="50%"
android:pivotY="50%"
/>
这里的缩放效果没有指定重复的次数,照片以自己图片为中心放大1.5倍后,最后显示的是1.5倍图片大小的效果。
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="4000"
android:fillAfter="true"
android:fromXDelta="0"
android:fromYDelta="0"
android:interpolator="@android:anim/cycle_interpolator"
android:toXDelta="0"
android:toYDelta="500" />
这里的平移效果比较简单只是从原来的位置往下平移500像素的距离,最后停留在那里。
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<alpha
android:duration="4000"
android:fromAlpha="1"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:repeatCount="1"
android:toAlpha="0.3"
/>
<rotate
android:duration="4000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="3"
android:toDegrees="1080" />
<scale
android:duration="4000"
android:fromXScale="0.5"
android:fromYScale="0.5"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.5"
android:toYScale="1.5" />
<translate
android:duration="4000"
android:fromXDelta="0"
android:fromYDelta="0"
android:interpolator="@android:anim/cycle_interpolator"
android:toXDelta="0"
android:toYDelta="500" />
set>
这里只是把上面几个动画效果拼接起来,作为一个动画效果,可以看到,这个动画效果,有透明的效果,有旋转的效果,有缩放的效果,有平移的效果。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="alpha"
android:text="透明动画" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="rotate"
android:text="旋转动画" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="scale"
android:text="大小动画" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="translate"
android:text="位置动画" />
LinearLayout>
<TextView
android:id="@+id/main_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@mipmap/mm"
android:text="Hello World!" />
LinearLayout>
这里设置几个按钮来选择动画效果的显示,还有一个TextView来显示动画的效果,这里的显示效果控件可以是各种控件,可以是图片ImageView也可以是其他的。
package com.lwz.tweenanimation;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.TextView;
public class MainActivity extends Activity {
//定义布局内的控件
TextView textView;
int index = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//实例化布局的内的控件
textView = (TextView) findViewById(R.id.main_text);
//定义操作补间动画的对象
Animation anima = AnimationUtils.loadAnimation(this, R.anim.anim_all);
textView.setAnimation(anima);
//给补间动画设置监听事件
anima.setAnimationListener(new Animation.AnimationListener() {
//动画开始的时候回调
@Override
public void onAnimationStart(Animation animation) {
Log.e("TAG", "start:" + index++);
}
//动画结束的时候回调
@Override
public void onAnimationEnd(Animation animation) {
Log.e("TAG", "end:" + index++);
}
//动画重复运行的时候回调
@Override
public void onAnimationRepeat(Animation animation) {
Log.e("TAG", "repeat:" + index++);
}
});
}
public void alpha(View view) {
Animation anima = AnimationUtils.loadAnimation(this, R.anim.alpha);
textView.setAnimation(anima);
}
public void rotate(View view) {
Animation anima = AnimationUtils.loadAnimation(this, R.anim.rotate);
textView.setAnimation(anima);
}
public void scale(View view) {
Animation anima = AnimationUtils.loadAnimation(this, R.anim.scale);
textView.setAnimation(anima);
}
public void translate(View view) {
Animation anima = AnimationUtils.loadAnimation(this, R.anim.translate);
textView.setAnimation(anima);
}
}
上面的代码可以显示各种动画的效果,其中这里也测试了一下动画的监听事件,可以在监听事件里面做其他事情,比如在一个动画结束时,马上执行另一个动画。
动画正在进行时点击其他的动画效果的按钮,会停止原来的动画效果,显示新点击的动画效果。
但是这个程序有一个debug就是,动画结束后再点击其他的动画效果是没有反应的。
比如:
TextView textView = (TextView) findViewById(R.id.main_text);
//定义操作补间动画的对象
Animation anima = AnimationUtils.loadAnimation(this, R.anim.anim_all);
textView.setAnimation(anima);
这里的R.anim.anim_all是资源文件
程序效果:小猪在页面上来回跑,并且脚是前后摆动的;
这个程序需要五张图片资源,一个大的背景图片,两张往前走的小猪的姿势图片,两张往回走的小猪的姿势图片。
这个程序可以使用很多方法来实现。
1.可以是图片的隐藏和显示的方法实现
小猪跑到最左边后隐藏,显示右边的小猪,一直重复上面的操作。
2.资源替换的方法
小猪跑到最左边后把动画效果和图片资源换成右边的小猪,一直重复上面的操作。
3.动画的时间监听来完成
小猪跑到最左边后把另一个动画效果切换,一直重复上面的操作。
但是无论任何都要使用到的是:
帧动画:使小猪的腿一直再跑的状态
补间动画:使小猪平移
这里使用的是两个小猪在一直跑的状态的方法:
第一个小猪从屏幕起点向右跑,一直跑到屏幕两倍的距离,一直重复这个动画;
第二个小猪在屏幕两倍距离多一点的位置开始跑,跑过屏幕左边为止为止。一直重复这个动画。
当第一个小猪跑过屏幕右边时,第二个小猪刚好从屏幕的右边界出现,看起来是同一个小猪在屏幕上来回跑。
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@mipmap/pig1"
android:duration="100" />
<item
android:drawable="@mipmap/pig2"
android:duration="100" />
animation-list>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@mipmap/pig3"
android:duration="100" />
<item
android:drawable="@mipmap/pig4"
android:duration="100" />
animation-list>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="10000"
android:fromXDelta="0"
android:fromYDelta="0"
android:repeatCount="infinite"
android:toXDelta="200%p"
android:toYDelta="0" />
set>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="10000"
android:fromXDelta="120%p"
android:fromYDelta="0"
android:toXDelta="-100%p"
android:repeatCount="infinite"
android:toYDelta="0" />
set>
第二个小猪的控件初始的位置是在屏幕的右边,所以再往右一个屏幕多一点,就是两个屏幕的距离。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/background"
tools:context="com.lwz.animation.MainActivity">
<TextView
android:id="@+id/main_iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="130dp"
android:background="@drawable/pig1_2" />
<TextView
android:id="@+id/main_iv2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginTop="150dp"
android:background="@drawable/pig3_4" />
RelativeLayout>
这里大背景在整个布局中,两个TextView来显示两个小猪。
package com.lwz.animation;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//第一只小猪
TextView tv = (TextView) findViewById(R.id.main_iv);
//帧动画的设置
AnimationDrawable animationDrawable = (AnimationDrawable) tv.getBackground();
animationDrawable.start();
//补间动画的设置
Animation animation = AnimationUtils.loadAnimation(this, R.anim.run);
tv.setAnimation(animation);
//对第二个小猪图片
TextView tv2 = (TextView) findViewById(R.id.main_iv2);
//帧动画的设置
AnimationDrawable animationDrawable2 = (AnimationDrawable) tv2.getBackground();
animationDrawable2.start();
//补间动画的设置
Animation animation2 = AnimationUtils.loadAnimation(MainActivity.this, R.anim.run2);
tv2.setAnimation(animation2);
}
}
这里的java代码都是比较简单的。
往前跑时:
这里就基本实现小猪来回跑的效果了,这里的第二个小猪要往右边的距离长一点是因为这里的小猪没有设置平移的速度,它在中间会加速前进,这里也可以设置两个小猪匀速前进。
这里使用一个小猪来完成来回跑的动画。
设计思路:
小猪跑到右边后,把背景资源和动画资源换掉
同样,小猪跑到左边后,再次把背景资源和动画资源换掉
这里就不再重复了,把第二个小猪的TextView控件删除就可以。
1.run.xml
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="85%p"
android:toYDelta="0" />
这里设置不用走完屏幕,大概刚走到右边边界就可以了,并且只需要执行一次动画就可以了。
2.run2.xml
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:fromXDelta="90%p"
android:fromYDelta="0"
android:toXDelta="0"
android:toYDelta="0" />
这里设置不用走完屏幕,大概刚走到左边边界就可以了,并且只需要执行一次动画就可以了。
package com.lwz.animation;
import android.app.Activity;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.TextView;
public class MainActivity extends Activity {
//布局内的控件
TextView tv;
//一个游标值,单数显示第一个动画,双数显示第二个动画
int index = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//实例化小猪
tv = (TextView) findViewById(R.id.main_iv);
runAlong(R.anim.run);
}
/**
* 这个方法涉及到不断的递归
*
* @param run
*/
private void runAlong(int run) {
if (index % 2 == 0) {
//设置单次的TextView的background属性
//帧动画的值
tv.setBackgroundResource(R.drawable.pig1_2);
//补间动画的属性值
run = R.anim.run;
}
//帧动画的设置
AnimationDrawable animationDrawable = (AnimationDrawable) tv.getBackground();
animationDrawable.start();
//补间动画的设置
Animation animation = AnimationUtils.loadAnimation(this, run);
tv.setAnimation(animation);
//给补间动画设置监听事件
animation.setAnimationListener(new Animation.AnimationListener() {
//动画结束时开始另一个动画
@Override
public void onAnimationEnd(Animation animation) {
//游标值加1
index++;
//设置第二次的TextView的background属性
//帧动画的值
tv.setBackgroundResource(R.drawable.pig3_4);
//设置补间动画的属性值,并且调用方法
runAlong(R.anim.run2);
}
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}
}
上面的代码也可以实现小猪来回跑的动画,并且效果更好。