废话少说,言归正传,下面用几个例子说明surfaceview的使用。
(一) 基本功能:用SurfaceView显示一副背景图片。 运行后的效果很简单,就是在屏幕上显示一副图片。
package com.pushBox;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class PushBoxActivity extends Activity {
//欢迎界面
WelcomeView welcomeView = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//显示欢迎界面
welcomeView = new WelcomeView( this );
setContentView( welcomeView );
}
//内部类,欢迎界面
class WelcomeView extends SurfaceView implements SurfaceHolder.Callback
{
private SurfaceHolder holder;
private WelcomeViewDrawThread welcomeViewDrawThread;
//背景图片,大小640 * 480
Bitmap background;
//图片显示的位置
int backgroundX = 0;
int backgroundY = 0;
public WelcomeView( Context context )
{
super( context );
holder = this.getHolder();
holder.addCallback( this );
background = BitmapFactory.decodeResource( getResources(), R.drawable.background );
//创建一个绘图线程
welcomeViewDrawThread = new WelcomeViewDrawThread( this, holder );
}
//自定义的绘图函数,具体的绘图在这里完成
public void onDraw( Canvas c )
{
c.drawBitmap( background, backgroundX, backgroundY, null );
}
@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
//启动绘图线程
welcomeViewDrawThread.setFlag( true );
welcomeViewDrawThread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
welcomeViewDrawThread.setFlag( false );
}
}
//内部类,欢迎界面的绘图线程
class WelcomeViewDrawThread extends Thread
{
private WelcomeView welcomeView;
private SurfaceHolder holder;
private boolean isRun;
private int sleepSpan = 200;
public WelcomeViewDrawThread( WelcomeView welcomeView, SurfaceHolder holder )
{
this.welcomeView = welcomeView;
this.holder = holder;
isRun = true;
}
public void setFlag( boolean flag )
{
isRun = flag;
}
@Override
public void run() {
// TODO Auto-generated method stub
while( isRun )
{
Canvas c = null;
try
{
c = holder.lockCanvas();
synchronized( holder )
{
//调用绘图函数
welcomeView.onDraw( c );
}
}finally
{
if( c != null )
{
holder.unlockCanvasAndPost( c );
}
}
try{
//睡眠200毫秒
Thread.sleep( sleepSpan );
}
catch(Exception e){
e.printStackTrace();
}
}
}
}
}
(二) 初露锋芒:用SurfaceView显示一个动态打开的门。运行后的效果,左右两扇门缓缓打开。
如果只用SurfaceView显示一副背景图片,那绝对是“大炮打蚊子”------大材小用。从主线程中拉出一个单独的线程,就是为了处理动态效果。这里具体实现的时候有两个线程:welcomeViewGoThread和welcomeViewDrawThread。welcomeViewGoThread只负责修改图片显示的座标,welcomeViewDrawThread负责在具体的位置显示图片。这种进一步分离,使得各模块的功能更加独立和明确。
package com.pushBox;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class PushBoxActivity extends Activity {
//欢迎界面
WelcomeView welcomeView = null;
//欢迎界面的动画线程
WelcomeViewGoThread welcomeViewGoThread = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//显示欢迎界面
welcomeView = new WelcomeView( this );
setContentView( welcomeView );
welcomeViewGoThread = new WelcomeViewGoThread( welcomeView );
//启动动画线程
welcomeViewGoThread.start();
}
//内部类,欢迎界面
class WelcomeView extends SurfaceView implements SurfaceHolder.Callback
{
private SurfaceHolder holder;
private WelcomeViewDrawThread welcomeViewDrawThread;
//背景图片,大小640 * 480
Bitmap background;
//左边的木门,大小180 * 450
Bitmap leftWood;
Bitmap rightWood;
//图片显示的位置
int backgroundX = 0;
int backgroundY = 0;
int leftWoodX = 10;
int leftWoodY = 15;
int rightWoodX = 150;
int rightWoodY = 15;
public WelcomeView( Context context )
{
super( context );
holder = this.getHolder();
holder.addCallback( this );
background = BitmapFactory.decodeResource( getResources(), R.drawable.background );
leftWood = BitmapFactory.decodeResource( getResources(), R.drawable.image33 );
rightWood = BitmapFactory.decodeResource( getResources(), R.drawable.image3 );
//创建一个绘图线程
welcomeViewDrawThread = new WelcomeViewDrawThread( this, holder );
}
//自定义的绘图函数,具体的绘图在这里完成
public void onDraw( Canvas c )
{
c.drawBitmap( background, backgroundX, backgroundY, null );
c.drawBitmap( leftWood, leftWoodX, leftWoodY, null );
c.drawBitmap( rightWood, rightWoodX, rightWoodY, null );
}
@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
//启动绘图线程
welcomeViewDrawThread.setFlag( true );
welcomeViewDrawThread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
welcomeViewDrawThread.setFlag( false );
}
}
//内部类,欢迎界面的动画线程,只修改座标,不负责具体显示
class WelcomeViewGoThread extends Thread
{
private WelcomeView welcomeView;
private int sleepSpan = 200;
private boolean isRun;
public WelcomeViewGoThread( WelcomeView welcomeView )
{
this.welcomeView = welcomeView;
isRun = true;
}
public void setFlag( boolean flag )
{
isRun = flag;
}
@Override
public void run() {
// TODO Auto-generated method stub
while( isRun )
{
// 修改木门座标
welcomeView.leftWoodX -= 2;
welcomeView.rightWoodX += 2;
if( welcomeView.leftWoodX < -90 )
{
welcomeView.leftWoodX = 10;
welcomeView.rightWoodX = 150;
}
try{
//睡眠200毫秒
Thread.sleep( sleepSpan );
}
catch(Exception e){
e.printStackTrace();
}
}
}
}
//内部类,欢迎界面的绘图线程
class WelcomeViewDrawThread extends Thread
{
private WelcomeView welcomeView;
private SurfaceHolder holder;
private boolean isRun;
private int sleepSpan = 200;
public WelcomeViewDrawThread( WelcomeView welcomeView, SurfaceHolder holder )
{
this.welcomeView = welcomeView;
this.holder = holder;
isRun = true;
}
public void setFlag( boolean flag )
{
isRun = flag;
}
@Override
public void run() {
// TODO Auto-generated method stub
while( isRun )
{
Canvas c = null;
try
{
c = holder.lockCanvas();
synchronized( holder )
{
//调用绘图函数
welcomeView.onDraw( c );
}
}finally
{
if( c != null )
{
holder.unlockCanvasAndPost( c );
}
}
try{
//睡眠200毫秒
Thread.sleep( sleepSpan );
}
catch(Exception e){
e.printStackTrace();
}
}
}
}
}
(三) 脱胎换骨:修改程序框架。
上述的程序框架有问题,所有代码都放在一个文件里。下面要做的就是把相关的class都独立出来。代码改起来也很简单,只要把几个内部类单独写到一个文件即可。
(四) 重出江湖:用SurfaceView实现一个完整的欢迎界面