安卓案例:利用定时器实现逐帧动画

一、运行效果

android帧动画实现 安卓逐帧动画制作器_消息处理

单击【开始】按钮,可以看到逐帧动画效果:

android帧动画实现 安卓逐帧动画制作器_android_02

单击【停止】按钮,可以停止动画效果。

二、涉及知识点

1、图像视图(ImageView)

2、按钮(Button)

3、定时器(Timer)

4、定时器任务(TimerTask)

5、消息处理器(Handler)

6、数组与循环

三、实现步骤

1、创建安卓应用GameSpecialEffect

android帧动画实现 安卓逐帧动画制作器_android_03

2、将逐帧动画素材(23张图片)拷贝到mipmap目录里

android帧动画实现 安卓逐帧动画制作器_消息处理_04

android帧动画实现 安卓逐帧动画制作器_android动画延迟执行_05

3、主布局资源文件acitivity_main.xml

android帧动画实现 安卓逐帧动画制作器_android帧动画实现_06

xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:gravity="center"
android:orientation="vertical"
tools:context="net.hw.game_special_effect.MainActivity">
android:id="@+id/iv_bomb"
android:layout_width="250dp"
android:layout_height="250dp"
android:src="@mipmap/img1" />
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
android:id="@+id/btn_start"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_marginRight="30dp"
android:background="#cccccc"
android:onClick="doStart"
android:text="@string/start" />
android:id="@+id/btn_stop"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:background="#cccccc"
android:onClick="doStop"
android:text="@string/stop" />

4、字符串资源文件strings.xml

android帧动画实现 安卓逐帧动画制作器_android帧动画实现_07

安卓案例:游戏特效

开始

停止

5、主界面类MainActivity

android帧动画实现 安卓逐帧动画制作器_消息处理_08

package net.hw.game_special_effect;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.ImageView;
import java.util.Timer;
import java.util.TimerTask;
/**
* Created by howard on 3/9/2018.
*/
public class MainActivity extends Activity {
/**
* 定时器
*/
private Timer timer;
/**
* 定时器任务
*/
private TimerTask task;
/**
* 消息处理器
*/
private Handler handler;
/**
* 图像视图
*/
private ImageView ivBomb;
/**
* 图像资源标识数组
*/
private int[] imgIds;
/**
* 图像索引
*/
private int imgIndex;
/**
* 图像总数
*/
private final int IMG_COUNT = 23;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 利用布局资源文件设置用户界面
setContentView(R.layout.activity_main);
// 通过资源标识获得控件实例
ivBomb = findViewById(R.id.iv_bomb);
// 初始化图像标识数组
imgIds = new int[IMG_COUNT];
for (int i = 0; i < IMG_COUNT; i++) {
/**

* 参数1:资源文件名

* 参数2:资源文件类型

* 参数3:包名

*/
imgIds[i] = getResources().getIdentifier("img" + (i + 1), "mipmap", "net.hw.game_special_effect");
}
// 创建消息处理器,处理从定时器任务里发送过来的消息
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
/*
消息内容msg.what存放的是当前图像索引
通过它从图像标识数组里获取当前图像的资源标识
然后通过此资源标识设置图像控件要显示的图像
*/
ivBomb.setImageResource(imgIds[msg.what]);
}
};
}
/**
* 开始按钮单击事件处理方法
*
* @param view
*/
public void doStart(View view) {
// 实例化定时器
timer = new Timer();
// 实例化定时器任务
task = new TimerTask() {
@Override
public void run() {
// 更新图像索引
imgIndex++;
imgIndex = imgIndex % IMG_COUNT;
// 将更新后的图像索引作为消息内容发送给主线程
handler.sendEmptyMessage(imgIndex);
}
};
// 对定时器任务进行调度
/**
* 参数1:定时器任务
* 参数2:首次执行延迟时间
* 参数3:定时执行的周期(毫秒)
*/
timer.schedule(task, 0, 100);
}
/**
* 停止按钮单击事件处理方法
*
* @param view
*/
public void doStop(View view) {
// 取消定时器任务
timer.cancel();
}
}

运行程序,测试运行效果:

android帧动画实现 安卓逐帧动画制作器_android帧动画实现_09

思考题:能够将定时器任务里的三行代码精简成一行代码?

android帧动画实现 安卓逐帧动画制作器_数组_10

android帧动画实现 安卓逐帧动画制作器_消息处理_11

但是这个代码有点小问题,程序运行时间足够长,会导致imgIndex溢出。

继续修改代码如下:

android帧动画实现 安卓逐帧动画制作器_android帧动画实现_12

四、小结

利用定时器(Timer对象)开辟子线程,定时执行任务(TimerTask对象),在任务里利用消息器的sendEmptyMessage方法或SendMessage方法发送消息,而在主线程创建消息处理器(Handler对象),在它的handleMessage(Message msg)方法里接收由子线程发送的消息,更新主线程的UI,从而实现动画效果。

其实,Timer与Handler结合实现动画,跟Thread与Handler结合实现动画,其实处理思路都是一样的。

五、课堂练习

android帧动画实现 安卓逐帧动画制作器_android帧动画实现_13