上一讲中,小编给大家介绍了Tween动画,今天小编给大家介绍一下Frame动画的制作,Frame动画就是换图(切帧),将若干张图片组成图组按一定的次序依次显示。这种图组可以是将一张图分割成若干张也可以是若干张完整的图。通过线程控制图片的切换,从而实现动画,今天带给大家的DEMO中有一个动画,我将向大家展示滚屏动画的实现方法。
package com.example.scrollview;
/**
* @author Arthur Lee
* @date 08/22/2014
* */
import android.os.Bundle;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.view.Menu;
import android.view.Window;
import android.view.WindowManager;
public class MainActivity extends Activity
{
GameView gameView;
@Override protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
gameView = new GameView(this);
setContentView(gameView);
}
@Override public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
package com.example.scrollview;
/**
* @author Arthur Lee
* @date 08/22/2014
* */
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GameView extends SurfaceView implements SurfaceHolder.Callback
{
MainActivity mainActivity;
Bitmap backgroundBitmap;//缩放前的背景图
Bitmap background;//缩放后的背景图
Bitmap[] backgrounds;//背景图切片数组
int length;//背景图切片数组,由当前屏幕宽度决定其值
Paint paint;
int pictureW = 10,pictureH = 540;
int screenW,screenH;//获取屏幕宽高
int backGroundIX = 0;//核心图的x坐标
int i = 0;//核心图的索引
TutoriolThread thread;
BackGroundThread bgThread;
public GameView(MainActivity mainActivity)
{
super(mainActivity);
// TODO Auto-generated constructor stub
getHolder().addCallback(this);//注册接口
this.mainActivity = mainActivity;
this.thread = new TutoriolThread(getHolder(), this);
this.bgThread = new BackGroundThread(this);
}
public void initPicture(){
paint = new Paint();
paint.setColor(Color.BLACK);
backgroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.beeground);//获取背景图
background = Bitmap.createScaledBitmap(backgroundBitmap, screenW, screenH, true);//对背景图进行缩放,以适应当前屏幕的大小。
length = screenW/10+((screenW%10==0)?0:1);//获取切片数目
pictureH = screenH;
pictureW = 10;
backgrounds = new Bitmap[length];//背景图切片数组
for(int i=0;i<backgrounds.length;i++){
backgrounds[i] = Bitmap.createBitmap(background, pictureW*i, 0, pictureW, pictureH);
}
//释放无用图片占据的空间。
backgroundBitmap = null;
background = null;
}
public void drawPicture(Canvas canvas){
int backGroundIX=this.backGroundIX;
int i=this.i;
//解决i左侧的问题
if(backGroundIX>0){
int n=(backGroundIX/pictureW)+((backGroundIX%pictureW==0)?0:1);//计算i左面有几幅图
for(int j=1;j<=n;j++){
canvas.drawBitmap(
backgrounds[(i-j+length)%length],
backGroundIX-pictureW*j,
0,
paint
);
}
}
//解决i自己
canvas.drawBitmap(backgrounds[i], backGroundIX, 0, paint);
//解决i右侧的问题
if(backGroundIX<screenW-pictureW){
int k=screenW-(backGroundIX+pictureW);
int n=(k/pictureW)+((k%pictureW==0)?0:1);//计算i右面有几幅图
for(int j=1;j<=n;j++){
canvas.drawBitmap(
backgrounds[(i+j)%length],
backGroundIX+pictureW*j,
0,
paint
);
}
}
}
@Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
// TODO Auto-generated method stub
}
@Override public void surfaceCreated(SurfaceHolder holder)
{
// TODO Auto-generated method stub
screenW = getWidth();
screenH = getHeight();
//初始化图片
initPicture();
//启动刷帧线程
this.thread.setFlag(true);
this.thread.start();
//启动滚屏线程
this.bgThread.setFlag(true);
this.bgThread.start();
initPicture();
}
@Override public void surfaceDestroyed(SurfaceHolder holder)
{
// TODO Auto-generated method stub
boolean retry = true;
this.thread.setFlag(false);
this.bgThread.setFlag(false);
while (retry) {
try {
thread.join();
bgThread.join();
retry = false;
}
catch (InterruptedException e) {//不断地循环,直到刷帧线程结束
}
}
}
//刷阵线程
class TutoriolThread extends Thread{
private SurfaceHolder surfaceHolder;
private GameView gameView;
private boolean flag = false;
public TutoriolThread(SurfaceHolder surfaceHolder, GameView gameView) {//构造器
this.surfaceHolder = surfaceHolder;
this.gameView = gameView;
}
public void setFlag(boolean flag) {//设置循环标记位
this.flag = flag;
}
@Override
public void run() {
Canvas c;
while (this.flag) {
c = null;
try {
// 锁定整个画布,在内存要求比较高的情况下,建议参数不要为null
c = this.surfaceHolder.lockCanvas(null);
synchronized (this.surfaceHolder) {
gameView.drawPicture(c);//绘制
//移动切图坐标,每次只移动一位
if(gameView.i == length)
gameView.i = 0;
else
gameView.i++;
}
} finally {
if (c != null) {
//更新屏幕显示内容
this.surfaceHolder.unlockCanvasAndPost(c);
}
}
try{
Thread.sleep(100);
}
catch(Exception e){
e.printStackTrace();
}
}
}
}
}
package com.example.scrollview;
/**
* @author Arthur Lee
* @date 08/22/2014
* */
public class BackGroundThread extends Thread
{
private int sleepSpan = 500;//睡眠的毫秒数
private int span = 1;//图片移动的步长
private boolean flag = true;//循环标志位
GameView gameView;//GameView的引用
public BackGroundThread(GameView gameView){//构造器
this.gameView = gameView;
}
public void setFlag(boolean flag){//设置标记位
this.flag = flag;
}
public void run(){
while(flag){
gameView.backGroundIX -= span;
if(gameView.backGroundIX <-gameView.pictureW){
gameView.backGroundIX+=gameView.pictureW;
}
}try{
Thread.sleep(sleepSpan);//睡眠
}catch(Exception e){//捕获异常
e.printStackTrace();//打印异常信息
}
}
}