欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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]
<?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","开始播放音效了...");
}
}
};
}