一、关于动画
动画有下面两种情况
同一个图形通过视图在界面上进行透明度,缩放,旋转,平移的变化(View动画)
在界面的同一个位置上不断切换显示不同的图片(Drawable动画)
动画的分类
View Animation
Drawable Animation
Android中提供了两种实现动画的方式
纯编码的方式
Xml配置的方式
动画在应用中是非常常见的界面效果, 也是提高用户体验的一种好手段
二、动画的分类
单一动画(Animation)
缩放动画(ScaleAnimation)
透明度动画(AlphaAnimation)
旋转动画(RotateAnimation)
平移动画(TranslateAnimation)
复合动画(AnimationSet)
由多个单一动画组合在一起的动画
三、相关API
1.Animation的公用功能
setDuration(long durationMillis) : 设置持续时间(单位ms)
setStartOffset(long startOffset) : 设置开始的延迟的时间(单位ms)
setFillBefore(boolean fillBefore) : 设置最终是否固定在起始状态
setFillAfter(boolean fillAfter) : 设置最终是否固定在最后的状态
setAnimationListener(AnimationListener listener) : 设置动画监听
坐标类型:
Animation.ABSOLUTE
Animation.RELATIVE_TO_SELF
Animation.RELATIVE_TO_PARENT
启动动画 : view.startAnimation(animation);
结束动画: view.clearAnimation()
动画监听器 : AnimationListener
onAnimationStart(Animation animation) : 动画开始的回调
onAnimationEnd(Animation animation) : 动画结束的回调
onAnimationRepeat(Animation animation) : 动画重复执行
2.缩放动画(Code ScaleAnimation)
ScaleAnimation(fromX, toX, fromY, toY, pivotXType, pivotXValue, pivotYType, pivotYValue);
fromX : 开始时X轴上的缩放比例 toX : 结束时X轴上的缩放比例
fromY :开始时Y轴上的缩放比例
toY :结束时Y轴上的缩放比例
pivotXType : X轴坐标的类型(计算x轴上的偏移量的方式)
pivotXVlaue : 中心点在X轴相对视图左顶点在x轴上的偏移量
pivotYType : Y轴坐标的类型(计算x轴上的偏移量的方式)
pivotYValue : 中心点相对视图左顶点在y轴上的偏移量
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="0"
android:fromYScale="0"
android:toXScale="1.5"
android:toYScale="1"
android:startOffset="1000"
android:duration="3000"
android:pivotX="100%"
android:pivotY="100%"
android:fillAfter="true">
</scale>
<!-- 宽度从0.0到1.5, 高度从0.0到1.0, 延迟1s开始,持续3s,圆心为右下角, 最终固定 -->
3.旋转动画(RotateAnimation)
RotateAnimation(fromDegrees, toDegrees, pivotXType, pivotXValue, pivotYType, pivotYValue);
fromDegrees : 开始时的角度toDegrees : 结束时的角度
pivotXType : X轴坐标的类型
pivotXVlaue : X轴坐标的值
pivotYType : Y轴坐标的类型
pivotYValue : Y轴坐标的值
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="90"
android:toDegrees="-90"
android:duration="5000">
</rotate>
<!-- 以左顶点为坐标, 从正90度到负90度, 持续5s -->
4.透明度动画(AlphaAnimation)
AlphaAnimation(fromAlpha, toAlpha);
fromAlpha : 开始时的缩放比例toAlpha : 结束时的缩放比例
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="1"
android:toAlpha="0"
android:duration="4000">
</alpha>
<!-- 从完全不透明到完全透明, 持续4s -->
5.平移动画(TranslateAnimation)
TranslateAnimation(fromXType, fromXValue, toXType, toXValue, fromYType, fromYValue, toYType, toYValue);
fromXType : 坐标类型fromXValue : 开始时X轴的坐标
toXType :坐标类型
toXValue : 结束时X轴的坐标
fromYType :坐标类型
fromYValue : 开始时Y轴的坐标
toYType :坐标类型
toYValue : 结束时Y轴的坐标
<?xml version="1.0" encoding="utf-8"?>
<translate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="100%p"
android:toXDelta="0"
android:fromYDelta="0"
android:toYDelta="0"
android:duration="2000">
</translate>
<!-- 从屏幕的右边逐渐回到原来的位置, 持续2s -->
6.复合动画(Code AnimationSet)
// 复合动画对象
AnimationSet animationSet = new AnimationSet(false);
// 添加一个单一动画
animationSet.addAnimation(alpha);
animationSet.addAnimation(rotate);
//开启动画
iv_animation.startAnimation(animationSet);
复合动画(Xml AnimationSet):
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<alpha
android:duration="2000"
android:fromAlpha="0"
android:toAlpha="1" >
</alpha>
<rotate
android:duration="2000"
android:fromDegrees="0"
android:startOffset="2000"
android:toDegrees="360" />
</set>
<!-- 透明度从透明到不透明, 持续2s, 接着进行旋转360度的动画, 持续2s -->
7.Interpolator属性的使用
Interpolator 被用来修饰动画效果,定义动画的变化率,可以使存在的动画效果accelerated(加速),decelerated(减速),repeated(重复)等。
@android:anim/linear_interpolator : 线性变化
@android:anim/accelerate_interpolator : 加速变化
@android:anim/decelerate_interpolator : 减速变化
@android:anim/cycle_interpolator : 周期循环变化
8.动画监听
在程序中可以对动画的特定时刻进行监听
Animation.setAnimationListener(AnimationListener listener) : 设置动画监听
动画监听器 : AnimationListener
onAnimationStart(Animation animation) : 动画开始的回调
onAnimationEnd(Animation animation) : 动画结束的回调
onAnimationRepeat(Animation animation) : 动画重复执行
9.动画配置
<animation-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/nv1" android:duration="500" />
<item android:drawable="@drawable/nv2" android:duration="500" />
<item android:drawable="@drawable/nv3" android:duration="500" />
<item android:drawable="@drawable/nv4" android:duration="500" />
</animation-list>
<ImageView
android:id="@+id/iv_dv"
android:layout_width=“80dp"
android:layout_height=“80dp"
android:layout_marginTop="160dp"
android:background="@drawable/anim_da" />
10.启动Drawable动画
//得到背景动画图上
AnimationDrawable ad = null;
ad = (AnimationDrawable) imageView.getBackground();
//启动动画
ad.start();
//停止动画
ad.stop();
四、代码实现:
package com.atguigu.l10_animation;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.TextView;
/*
* 编码实现View Animation
* 1. Code方式
* 2. Xml方式
*/
public class VAActivity extends Activity {
private ImageView iv_animation;
private TextView tv_animation_msg;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animation_va);
iv_animation = (ImageView) findViewById(R.id.iv_animation);
tv_animation_msg = (TextView) findViewById(R.id.tv_animation_msg);
}
/*
* 1.1 编码实现: 缩放动画
* ScaleAnimation
*/
/*
//1. 创建动画对象
//2. 设置
//3. 启动动画
*/
public void startCodeScale(View v) {
tv_animation_msg.setText("Code缩放动画: 宽度从0.5到1.5, 高度从0.0到1.0, 缩放的圆心为顶部中心点,延迟1s开始,持续2s,最终还原");
//1. 创建动画对象
ScaleAnimation animation = new ScaleAnimation(0.5f, 1.5f, 0, 1,
Animation.ABSOLUTE, iv_animation.getWidth()/2, Animation.ABSOLUTE, 0);
animation = new ScaleAnimation(0.5f, 1.5f, 0, 1,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0);
//2. 设置
//延迟1s开始
animation.setStartOffset(1000);
//持续2s
animation.setDuration(2000);
//最终还原
animation.setFillBefore(true);
//3. 启动动画
iv_animation.startAnimation(animation);
}
/*
* 1.2 xml实现: 缩放动画
* <scale>
*/
/*
1. 定义动画文件
2. 加载动画文件得到动画对象
3. 启动动画
*/
public void startXmlScale(View v) {
tv_animation_msg.setText("Xml缩放动画: Xml缩放动画: 宽度从0.0到1.5, 高度从0.0到1.0, 延迟1s开始,持续3s,圆心为右下角, 最终固定");
//1. 定义动画文件
//2. 加载动画文件得到动画对象
Animation animation = AnimationUtils.loadAnimation(this, R.anim.scale_test);
//3. 启动动画
iv_animation.startAnimation(animation);
}
/*
* 2.1 编码实现: 旋转动画
* RotateAnimation
*/
public void startCodeRotate(View v) {
tv_animation_msg.setText("Code旋转动画: 以图片中心点为中心, 从负90度到正90度, 持续5s");
//1. 创建动画对象
RotateAnimation animation = new RotateAnimation(-90, 90, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
//2. 设置
animation.setDuration(5000);
//3. 启动动画
iv_animation.startAnimation(animation);
}
/*
* 2.2 xml实现: 旋转动画
* <rotate>
*/
public void startXmlRotate(View v) {
tv_animation_msg.setText("Xml旋转动画: 以左顶点为坐标, 从正90度到负90度, 持续5s");
//1. 定义动画文件
//2. 加载动画文件得到动画对象
Animation animation = AnimationUtils.loadAnimation(this, R.anim.rotate_test);
//3. 启动动画
iv_animation.startAnimation(animation);
}
/*
* 3.1 编码实现: 透明度动画
* 完全透明 : 0
* 完全不透明 : 1
* AlphaAnimation
*/
public void startCodeAlpha(View v) {
tv_animation_msg.setText("Code透明度动画: 从完全透明到完全不透明, 持续2s");
//1. 创建动画对象
AlphaAnimation animation = new AlphaAnimation(0, 1);
// 2. 设置
animation.setDuration(4000);
// 3. 启动动画
iv_animation.startAnimation(animation);
}
/*
* 3.2 xml实现: 透明度动画
* <alpha>
*/
public void startXmlAlpha(View v) {
tv_animation_msg.setText("Xml透明度动画: 从完全不透明到完全透明, 持续4s");
//1. 定义动画文件
//2. 加载动画文件得到动画对象
Animation animation = AnimationUtils.loadAnimation(this, R.anim.alpha_test);
animation.setFillAfter(true);
//3. 启动动画
iv_animation.startAnimation(animation);
}
/*
* 4.1 编码实现: 平移动画
* TranslateAnimation
*/
public void startCodeTranslate(View v) {
tv_animation_msg.setText("Code移动动画: 向右移动一个自己的宽度, 向下移动一个自己的高度, 持续2s");
//1. 创建动画对象
TranslateAnimation animation = new TranslateAnimation(Animation.ABSOLUTE, 0, Animation.RELATIVE_TO_SELF, 1, Animation.ABSOLUTE, 0, Animation.RELATIVE_TO_SELF, 1);
//2. 设置
animation.setDuration(2000);
//3. 启动动画
iv_animation.startAnimation(animation);
}
/*
* 4.2 xml实现: 平移动画
* <translate>
*/
public void startXmlTranslate(View v) {
tv_animation_msg.setText("xml移动动画: 从屏幕的右边逐渐回到原来的位置, 持续2s"); //***此效果用于界面切换的动画效果
//1. 定义动画文件
//2. 加载动画文件得到动画对象
Animation animation = AnimationUtils.loadAnimation(this, R.anim.translate_test);
//3. 启动动画
iv_animation.startAnimation(animation);
}
/*
* 5.1 编码实现: 复合动画
* AnimationSet
*/
public void startCodeAnimationSet(View v) {
tv_animation_msg.setText("Code复合动画: 透明度从透明到不透明, 持续2s, 接着进行旋转360度的动画, 持续1s");
//1.创建透明动画并设置
AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
alphaAnimation.setDuration(2000);
//2.创建旋转动画并设置
RotateAnimation rotateAnimation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setDuration(1000);
rotateAnimation.setStartOffset(2000);//延迟
//3.创建复合动画对象
AnimationSet animationSet = new AnimationSet(true);
//4.添加两个动画
animationSet.addAnimation(alphaAnimation);
animationSet.addAnimation(rotateAnimation);
//5.启动复合动画
iv_animation.startAnimation(animationSet);
}
/*
* 5.2 xml实现: 复合动画
* <set>
*/
public void startXmlAnimationSet(View v) {
tv_animation_msg.setText("Xml复合动画: 透明度从透明到不透明, 持续2s, 接着进行旋转360度的动画, 持续2s");
//1. 定义动画文件
//2. 加载动画文件得到动画对象
Animation animation = AnimationUtils.loadAnimation(this, R.anim.set_test);
//3. 启动动画
iv_animation.startAnimation(animation);
}
/*
* 6. 测试动画监听
*/
public void testAnimationListener(View v) {
tv_animation_msg.setText("测试动画监听");
//tv_animation_msg.setText("Xml旋转动画: 以左顶点为坐标, 从正90度到负90度, 持续5s");
//1. 定义动画文件
//2. 加载动画文件得到动画对象
Animation animation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animation.setDuration(1000);
//设置线性变化
animation.setInterpolator(new LinearInterpolator());
//设置变化率
//设置动画重复次数
animation.setRepeatCount(Animation.INFINITE);//重复3次
//设置动画监听
animation.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
Log.e("TAG", "动画开始");
}
@Override
public void onAnimationRepeat(Animation animation) {
Log.e("TAG", "动画重复");
}
@Override
public void onAnimationEnd(Animation animation) {
Log.e("TAG", "动画结束");
}
});
//3. 启动动画
iv_animation.startAnimation(animation);
}
}
package com.atguigu.l10_animation;
import android.app.Activity;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
/*
* 测试: Drawable Animation
*/
public class DAActivity extends Activity implements OnClickListener {
private ImageView iv_da_mm;
private Button btn_da_start;
private Button btn_da_stop;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animation_da);
iv_da_mm = (ImageView) findViewById(R.id.iv_da_mm);
btn_da_start = (Button) findViewById(R.id.btn_da_start);
btn_da_stop = (Button) findViewById(R.id.btn_da_stop);
btn_da_start.setOnClickListener(this);
btn_da_stop.setOnClickListener(this);
}
private AnimationDrawable animationDrawable;
@Override
public void onClick(View v) {
if (v == btn_da_start) {
if(animationDrawable==null) {
//得到背景动画图片对象
animationDrawable = (AnimationDrawable) iv_da_mm.getBackground();
//启动
animationDrawable.start();
}
} else if (v == btn_da_stop) {
if(animationDrawable!=null) {
animationDrawable.stop();
animationDrawable = null;
}
}
}
}