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

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

一、运行效果

安卓案例:利用定时器实现逐帧动画_第1张图片

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

安卓案例:利用定时器实现逐帧动画_第2张图片

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

二、涉及知识点

1、图像视图(ImageView)

2、按钮(Button)

3、定时器(Timer)

4、定时器任务(TimerTask)

5、消息处理器(Handler)

6、数组与循环

三、实现步骤

1、创建安卓应用GameSpecialEffect

安卓案例:利用定时器实现逐帧动画_第3张图片

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

安卓案例:利用定时器实现逐帧动画_第4张图片

安卓案例:利用定时器实现逐帧动画_第5张图片

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

安卓案例:利用定时器实现逐帧动画_第6张图片




    

    

        

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

安卓案例:利用定时器实现逐帧动画_第7张图片


    安卓案例:游戏特效
    开始
    停止

5、主界面类MainActivity

安卓案例:利用定时器实现逐帧动画_第8张图片

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();
    }
}

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

安卓案例:利用定时器实现逐帧动画_第9张图片

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

安卓案例:利用定时器实现逐帧动画_第10张图片

安卓案例:利用定时器实现逐帧动画_第11张图片

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

继续修改代码如下:

安卓案例:利用定时器实现逐帧动画_第12张图片

四、小结

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

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

五、课堂练习

安卓案例:利用定时器实现逐帧动画_第13张图片

你可能感兴趣的:(安卓应用开发)