概述:
最近在讀himi的android遊戲開發專欄,其中通過前幾張剖析View的繼承介面類發現SurfaceView比較適合做Game Dev然後本人也動手跟著himi的代碼敲了幾下。最終雖然也達到了himi的運行效果。但是其中還是經過了好多疑點。現在本人將自己的理解發布出來,歡迎交流與學習
Code List:
[java]
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
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.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
public class LoginView extends SurfaceView implements Callback,Runnable{
private Canvas canvas; //定義畫布對象
private Thread thread; //定義線程線程對應
private int ScreenW,ScreenH; //定義螢幕的寬度和高度
private Paint paint; //定義畫筆對象
private SurfaceHolder sh; //聲明SurfaceHolder對象
private Resources resources; //聲明資來源物件
private Bitmap bitmapr; //註冊bitmap
private Bitmap bitmapb; //背景bitmap
private int bp_x,bp_y; //註冊背景圖寬度高�?
private boolean flag;
public static String zh_k = "註冊頁面";
private boolean zh_flag = true;
private String str_pass = "aaa";
//初始構�?
public LoginView(Context context) {
super(context);
//
resources = this.getResources();
bitmapr = BitmapFactory.decodeResource(resources, R.drawable.register); //註冊視窗
bitmapb = BitmapFactory.decodeResource(resources, R.drawable.duola); //註冊背景�?
thread = new Thread(this);
sh = this.getHolder();
sh.addCallback(this);
paint = new Paint();
paint.setColor(Color.RED);
paint.setAntiAlias(true); //去掉鋸齒
this.setFocusable(true);
this.setKeepScreenOn(true); //設定螢幕常亮
resources = this.getResources();
}
public void draw(){
canvas = sh.lockCanvas(); //得到畫布對象
paint.setColor(Color.RED);
if(null != canvas){ //在設定橫屏的時候 座標演算法如下
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(bitmapb,
-(bitmapb.getWidth() - ScreenW), -(bitmapb
.getHeight() - ScreenH), paint);
//2、3參數為x座標和y座標,就是位元影像paint的左上方位置
canvas.drawBitmap(bitmapr, bp_x,bp_y, paint);
sh.unlockCanvasAndPost(canvas);
}
}
@Override
public void run() {
while(!flag){
draw();
try {
thread.sleep(1000);
} catch (Exception e) {
Log.v("run", "error");
}
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
ScreenW = this.getWidth();
ScreenH = this.getHeight();
bp_x = ScreenW/2-bitmapr.getWidth()/2;
bp_y = ScreenH/2-bitmapr.getHeight()/2;
thread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
if(x > bp_x+14 && x < bp_x+129){ //鎖定登陸框姓名地區X軸
if(y >= bp_y+43 && y <= bp_y+58){ //鎖定登陸框姓名地區Y軸
Intent intent = new Intent();
intent.putExtra("name", "zhanglei");
intent.setClass(MainActivity.instance, Register.class);
MainActivity.instance.startActivity(intent);
}
}
return super.onTouchEvent(event);
}
}
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
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.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
public class LoginView extends SurfaceView implements Callback,Runnable{
private Canvas canvas; //定義畫布對象
private Thread thread; //定義線程線程對應
private int ScreenW,ScreenH; //定義螢幕的寬度和高度
private Paint paint; //定義畫筆對象
private SurfaceHolder sh; //聲明SurfaceHolder對象
private Resources resources; //聲明資來源物件
private Bitmap bitmapr; //註冊bitmap
private Bitmap bitmapb; //背景bitmap
private int bp_x,bp_y; //註冊背景圖寬度高�?
private boolean flag;
public static String zh_k = "註冊頁面";
private boolean zh_flag = true;
private String str_pass = "aaa";
//初始構�?
public LoginView(Context context) {
super(context);
//
resources = this.getResources();
bitmapr = BitmapFactory.decodeResource(resources, R.drawable.register); //註冊視窗
bitmapb = BitmapFactory.decodeResource(resources, R.drawable.duola); //註冊背景�?
thread = new Thread(this);
sh = this.getHolder();
sh.addCallback(this);
paint = new Paint();
paint.setColor(Color.RED);
paint.setAntiAlias(true); //去掉鋸齒
this.setFocusable(true);
this.setKeepScreenOn(true); //設定螢幕常亮
resources = this.getResources();
}
public void draw(){
canvas = sh.lockCanvas(); //得到畫布對象
paint.setColor(Color.RED);
if(null != canvas){ //在設定橫屏的時候 座標演算法如下
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(bitmapb,
-(bitmapb.getWidth() - ScreenW), -(bitmapb
.getHeight() - ScreenH), paint);
//2、3參數為x座標和y座標,就是位元影像paint的左上方位置
canvas.drawBitmap(bitmapr, bp_x,bp_y, paint);
sh.unlockCanvasAndPost(canvas);
}
}
@Override
public void run() {
while(!flag){
draw();
try {
thread.sleep(1000);
} catch (Exception e) {
Log.v("run", "error");
}
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
ScreenW = this.getWidth();
ScreenH = this.getHeight();
bp_x = ScreenW/2-bitmapr.getWidth()/2;
bp_y = ScreenH/2-bitmapr.getHeight()/2;
thread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
if(x > bp_x+14 && x < bp_x+129){ //鎖定登陸框姓名地區X軸
if(y >= bp_y+43 && y <= bp_y+58){ //鎖定登陸框姓名地區Y軸
Intent intent = new Intent();
intent.putExtra("name", "zhanglei");
intent.setClass(MainActivity.instance, Register.class);
MainActivity.instance.startActivity(intent);
}
}
return super.onTouchEvent(event);
}
}
運行:
方法執行順序:
LoginView-->surfaceCreated-->run-->draw
方法解析:
LoginView方法:
OK,我們看到LoginView其實是在初始化本View的一些全域變數,包括線程對象、位元影像對象。另外設定了一些效果,包括去掉鋸齒等。程式中注釋特別明朗
surfaceCreated方法:
本方法體中我們看到初始化了2組長度和高度。其中Sreen顧名思義我就不再解釋。bp_x和bp_y指的是註冊圖片在螢幕中的開始座標的位置。也就是左上方的位置[演算法解析:“螢幕的一半座標為中心點座標-註冊圖片一半的像素值”]得到的就為繪製圖片位元影像的起始位置。你明白了嗎?
run方法:
run方法為thread線程開始的跑的標示,代碼邏輯很簡單不再解釋
draw方法:
OK,本人覺得draw方法才是一個View中最核心的內容。因為它負責在螢幕上繪製內容和重新整理內容。本人將himi部落格的內容簡單化了很多。應該很好理解吧。
拿到canvas到畫兩個位元影像其中的注釋寫的很清楚本人不再多說
注意:
本人在做此案例的時候遇到了1個特別棘手的問題那就是按照himi的原始碼自己new的一個項目居然在paint位元影像的時候遇到了錯亂的問題。
說明:
登陸視窗的使用者名稱和密碼的點擊事件是通過重寫onTouchEvent方法來實現的。鎖定了相關的像素座標地區。如果該地區被點擊了就發送一個Intent。其中Intent的傳參為put的那個方法,另外在AndroidManifest.xml檔案中注意聲明你Intent跳轉的Activity
聲明:本人也是一名Android新手,歡迎大家一起交流與學習。稍後本人將發布本博文的源碼地址。因為公司網路不好,可能會在晚上回家之後upload上去