Android 之 Frame逐帧动画
程序员文章站
2022-03-16 16:15:27
...
[color=red][b][size=large][align=center]Android 动画[/align][/size][/b][/color]
[size=small][b][color=olive]Andorid 平台提供了两类动画:
一:Tween(补间动画),即通过对场景里面的对象不断做图像变化(平移、缩放、旋转)产生动画效果;
二:Frame(逐帧动画),即顺序播放事先准备好的图像,跟电影类似;
Frame动画:
实现:
xml文件实现:
编码实现:
举例:xml实现过程:
定义xml文件,将该文件放在/res 下的anim或drawable目录中,文件名可以
作为资源ID 在代码中引用;
说明:<animation-list>元素是必须的,并且必须作为根元素,可以包含一个或
多个<item>元素;
<animation-list>属性:android:oneshot="" 是否循环播放,false表示循环,可选,默认false
<item>元素属性:android:drawble="" 指定此帧动画所对应的图片资源;
android:duration="" 代表此帧持续的时间,为整数,毫秒;
例如:
提示:图片资源的存放,根据帧图片的大小放大对应的资源目录中;
编码实现:
* 创建AnimationDrawable 对象,装载xml动画文件;
* 设置控件背景资源为对应的AnimationDrawable对象;
AnimationDrawable 类中方法的介绍:
start(); 开始
stop(); 停止
setAlpha(100); 设置帧动画的透明度 (0-255)
setOneShot(); 设置是否播放一遍帧动画;
isRunning(); 是否正在播放
isOneShot(); 是否只播放一遍
getNmberOfFrames(); 返回帧动画的帧数,即<item> 标签数;
getFrame(); 根据索引得到指定帧的Drawable对象; 索引0开始;
getDuration(); 获得指定帧停留时间;
addFrame(); 向AnimationDrawable对象中添加新的帧;[/color][/b][/size]
[size=medium][color=red]
案例:小鸟飞翔,撞击并发出声音:[/color][/size]
[size=small][color=brown][b]res/anim 下的动画文件:[/b][/color][/size]
[size=small][color=brown][b]
布局文件如下:[/b][/color][/size]
[size=large][color=red][b]主程序入口:[/b][/color][/size]
[size=medium][color=blue][b]自定义视图控件,便于控制图片的变化:[/b][/color][/size]
[size=small][color=cyan][b]对自定义控件的使用,以及对应的效果:[/b][/color][/size]
[size=small][b][color=olive]Andorid 平台提供了两类动画:
一:Tween(补间动画),即通过对场景里面的对象不断做图像变化(平移、缩放、旋转)产生动画效果;
二:Frame(逐帧动画),即顺序播放事先准备好的图像,跟电影类似;
Frame动画:
实现:
xml文件实现:
编码实现:
举例:xml实现过程:
定义xml文件,将该文件放在/res 下的anim或drawable目录中,文件名可以
作为资源ID 在代码中引用;
说明:<animation-list>元素是必须的,并且必须作为根元素,可以包含一个或
多个<item>元素;
<animation-list>属性:android:oneshot="" 是否循环播放,false表示循环,可选,默认false
<item>元素属性:android:drawble="" 指定此帧动画所对应的图片资源;
android:duration="" 代表此帧持续的时间,为整数,毫秒;
例如:
提示:图片资源的存放,根据帧图片的大小放大对应的资源目录中;
编码实现:
* 创建AnimationDrawable 对象,装载xml动画文件;
* 设置控件背景资源为对应的AnimationDrawable对象;
AnimationDrawable 类中方法的介绍:
start(); 开始
stop(); 停止
setAlpha(100); 设置帧动画的透明度 (0-255)
setOneShot(); 设置是否播放一遍帧动画;
isRunning(); 是否正在播放
isOneShot(); 是否只播放一遍
getNmberOfFrames(); 返回帧动画的帧数,即<item> 标签数;
getFrame(); 根据索引得到指定帧的Drawable对象; 索引0开始;
getDuration(); 获得指定帧停留时间;
addFrame(); 向AnimationDrawable对象中添加新的帧;[/color][/b][/size]
[size=medium][color=red]
案例:小鸟飞翔,撞击并发出声音:[/color][/size]
[size=small][color=brown][b]res/anim 下的动画文件:[/b][/color][/size]
<?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/bird00" android:duration="180"></item>
<item android:drawable="@drawable/bird01" android:duration="180"></item>
<item android:drawable="@drawable/bird02" android:duration="180"></item>
<item android:drawable="@drawable/bird03" android:duration="180"></item>
<item android:drawable="@drawable/bird04" android:duration="180"></item>
<item android:drawable="@drawable/bird05" android:duration="180"></item>
<item android:drawable="@drawable/bird06" android:duration="180"></item>
<item android:drawable="@drawable/bird07" android:duration="180"></item>
<item android:drawable="@drawable/bird08" android:duration="180"></item>
<item android:drawable="@drawable/bird09" android:duration="180"></item>
<item android:drawable="@drawable/bird10" android:duration="180"></item>
</animation-list>
[size=small][color=brown][b]
布局文件如下:[/b][/color][/size]
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:orientation="vertical" >
<!-- 自定义控件 -->
<com.sun.frame.MyImageView
android:id="@+id/imageview1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
[size=large][color=red][b]主程序入口:[/b][/color][/size]
package com.sun.frame;
import android.app.Activity;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
public class MainActivity extends Activity {
private ImageView imageview ;
private AnimationDrawable ad; //
// 数据初始化
public void init(){
imageview = (ImageView) findViewById(R.id.imageview1);
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
imageview.setOnClickListener(listener);
}
// 点击事件监听器
private View.OnClickListener listener = new View.OnClickListener() {
public void onClick(View v) {
if(ad.isRunning()){
ad.stop();
}else
ad.start();
}
};
/**
* Activity 呈现给用户的时候调用的
*/
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
ad = (AnimationDrawable) getResources().getDrawable(R.anim.frame);
imageview.setBackgroundDrawable(ad);
}
}
[size=medium][color=blue][b]自定义视图控件,便于控制图片的变化:[/b][/color][/size]
package com.sun.frame;
import java.lang.reflect.Field;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.AnimationDrawable;
import android.media.AudioManager;
import android.media.SoundPool;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;
public class MyImageView extends ImageView {
public AnimationDrawable animationDrawable;
private Field field; // 领域对象
private SoundPool sp;
private int music;
/**
* 初始化数据
*
* @param context
* @param attrs
*/
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
Log.i("msg","MyImageView构造方法...");
/* 参数:
* 1、 播放数据流的最大个数
* 2、数据流类型
* 3、声音质量
*/
sp = new SoundPool(10, AudioManager.STREAM_SYSTEM, 5);
music = sp.load(context, R.raw.a2, 1);
// Log.i("msg","MyImageView构造方法...");
}
/**
* 画一次图调用一次 功能:用于监听每帧动画的播放状态
*/
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.i("msg", "onDraw()...");
try {
field = AnimationDrawable.class.getDeclaredField("mCurFrame");
field.setAccessible(true); // 设置可以访问
// 获取mCurFrame变量的当前值
int curFrame = field.getInt(animationDrawable);
if (curFrame == 29) {
//animationDrawable.stop(); // 停止播放
// 播放音乐特效
sp.play(music, 1, 1, 0, 0, 1);
Log.i("msg", "特效出来啦...");
// 设置动画的播放位置
//field.setInt(animationDrawable, 0); // 从0 开始
}else{
sp.pause(music);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
[size=small][color=cyan][b]对自定义控件的使用,以及对应的效果:[/b][/color][/size]
package com.sun.frame;
import android.app.Activity;
import android.graphics.drawable.AnimationDrawable;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
/**
* 自定义控件的使用
* @author Administrator
*
*注意:在AnimationDrawable 类中有一个mCurFrame变量,int型,保存当前动画的
*播放位置;改变量为私有的,所以只能通过反射机制读写private变量
*
*/
public class UserFrameActivity extends Activity {
private MyImageView image;
private AnimationDrawable ad; // 控制动画
private SoundPool sp ; //音效池 -- 小鸟叫
private int music; // 音乐
// 程序入口
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.code_frame);
// 获取控件对象,该对象为自定义对象
image = (MyImageView) findViewById(R.id.imageview1);
image.setOnClickListener(listener);
// 音效初始化
sp = new SoundPool(10, AudioManager.STREAM_SYSTEM, 5);
music = sp.load(this, R.raw.a3,1); //加载音乐
Log.i("msg", "onCreate()...");
}
/**
* Activity 呈现给用户时调用
*/
public void onWindowFocusChanged(boolean hasFocus) {
// TODO Auto-generated method stub
super.onWindowFocusChanged(hasFocus);
Log.i("msg","UserFrameActivity.onWindowFocusChanged()...");
image.setBackgroundResource(R.anim.frame_c); // 设置背景资源
ad = (AnimationDrawable) image.getBackground();
image.animationDrawable = ad; // 同步
ad.start();
sp.play(music, 1, 1, 0, -1, 1);
}
// 点击监听器
private OnClickListener listener = new OnClickListener() {
public void onClick(View v) {
if(ad.isRunning()){
ad.stop();
sp.pause(music); // 停止音效
Log.i("msg", "音效停止了...");
}else{
ad.start();
sp.resume(music); //(music, 1, 1, 0, -1, 1); // 播放音效
Log.i("msg","开始播放音效了...");
}
}
};
}