廢話少說,言歸正傳,下面用幾個例子說明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實現一個完整的歡迎界面