|
Android游戲開發(fā)之單點觸摸與多點觸摸的響應方式
游戲開發(fā)中的觸摸事件
在游戲開發(fā)中監(jiān)聽屏幕觸摸事件須要在View中重寫父類onTouchEvent方法,在重寫的方法中攔截用戶觸摸屏幕的一些信息,比如觸摸屏幕的X 、 Y坐標 觸摸屏幕發(fā)生的事件 觸摸按下 觸摸抬起 觸摸移動,觸摸屏幕發(fā)生的時間 等等, 我們先看看onTouchEvent的函數(shù)原型。
函數(shù)中的Event 參數(shù)的意思為當前觸摸事件的對象,這個對象中包含著當前觸摸事件的一切信息。比如ecent.getAction()可以拿到當前觸摸事件的名稱,根據(jù)觸摸事件的名稱可以判斷當前是觸摸按下 還是 觸摸移動 還是 觸摸抬起。 event.getX()與 event.getY()可以拿到當前觸摸屏幕的X Y坐標。event.getEventTime(); 可以拿到當前觸發(fā)觸摸事件的時間,等等所有的信息。 - @Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
mPosX = (int) event.getX();
mPosY = (int) event.getY();
switch (action) {
// 觸摸按下的事件
case MotionEvent.ACTION_DOWN:
Log.v("test", "ACTION_DOWN");
break;
// 觸摸移動的事件
case MotionEvent.ACTION_MOVE:
Log.v("test", "ACTION_MOVE");
break;
// 觸摸抬起的事件
case MotionEvent.ACTION_UP:
Log.v("test", "ACTION_UP");
break;
}
// return super.onTouchEvent(event);
return true;
}
復制代碼 這個函數(shù)是具有有返回值的,須要返回一個布爾值。大家發(fā)現(xiàn)我將return super.onTouchEvent(event)注釋掉了而是直接return ture。 我給同學們解釋一下為什么要著么操作。onTouchEvent方法不是我們手動調(diào)用的而是系統(tǒng)調(diào)用的 它的返回值會直接通知系統(tǒng)是否回調(diào)方法。如果說在這里return false onTouchEvent方法永遠不會在被回調(diào)也就是說它只能響應觸摸按下操作,觸摸移動事件 和觸摸抬起事件永遠都不會在被響應 ,log只會打印出"ACTION_DOWN"。 如果這里return super.onTouchEvent(event); 調(diào)用父類的方法來得到返回值返回 ,這樣也是有問題的因為調(diào)用父類的onTouchEvent方法可能也會返回false 這樣一來依然會無法響應觸摸移動事件和觸摸抬起事件。所以為了正確的處理觸摸事件在這里我們直接return ture 這樣一來就萬無一失了,Log中會將所有信息都打印出來。
1.單點觸摸
在下面這個DEMO中 用手觸摸 移動 屏幕后 下面的icon圖片會跟隨這我的手勢移動。 代碼實現(xiàn)主要是在onTouchEvent方法中時時去計算手觸摸屏幕各個狀態(tài)的坐標 然后調(diào)用 postInvalidate(); 方法去通知UI刷新屏幕重新顯示圖片 文字的位置以及內(nèi)容。 具體相關(guān)內(nèi)容見Android游戲開發(fā)之構(gòu)建游戲框架View與SurFaceView的區(qū)別(五)
- import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
public class ViewActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyView(this));
}
public class MyView extends View {
/** 觸摸后繪制的圖片 **/
Bitmap mBitmap = null;
/** 游戲畫筆 **/
Paint mPaint = null;
/** 觸摸后在屏幕中顯示的位置 **/
int mPosX = 0;
int mPosY = 0;
/**事件觸發(fā)時間**/
Long mActionTime = 0L;
public MyView(Context context) {
super(context);
/** 設置當前View擁有控制焦點 **/
this.setFocusable(true);
/** 設置當前View擁有觸摸事件 **/
this.setFocusableInTouchMode(true);
/** 加載圖片 **/
mBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.item);
mPaint = new Paint();
mPaint.setColor(Color.WHITE);
}
@Override
protected void onDraw(Canvas canvas) {
/** 繪制圖片 **/
canvas.drawBitmap(mBitmap, mPosX, mPosY, mPaint);
canvas.drawText("當前X坐標:"+mPosX, 0, 20, mPaint);
canvas.drawText("當前Y坐標:"+mPosY, 0, 40, mPaint);
canvas.drawText("事件觸發(fā)時間:"+mActionTime, 0, 60, mPaint);
super.onDraw(canvas);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
mPosX = (int) event.getX();
mPosY = (int) event.getY();
switch (action) {
// 觸摸按下的事件
case MotionEvent.ACTION_DOWN:
Log.v("test", "ACTION_DOWN");
break;
// 觸摸移動的事件
case MotionEvent.ACTION_MOVE:
Log.v("test", "ACTION_MOVE");
break;
// 觸摸抬起的事件
case MotionEvent.ACTION_UP:
Log.v("test", "ACTION_UP");
break;
}
/**得到事件觸發(fā)時間**/
mActionTime = event.getEventTime();
/** 通知UI線程刷新屏幕 **/
postInvalidate();
// return super.onTouchEvent(event);
return true;
}
}
}
復制代碼 2.多點觸摸
由于模擬器只能用鼠標點擊一個點 無法模擬多點觸摸,所以我用真機來調(diào)試多點觸摸。下面這張圖是我用豌豆莢在真機中截的圖,此時我兩只手指正在手機屏幕中觸摸移動。界面中正確的根據(jù)我的手勢來移動圖片以及顯示的內(nèi)容。這里強調(diào)一下多點觸摸并不是所有手機都支持 有些手機支持很多點有些手機可能只支持單點。就那我的手機來說只支持兩點觸摸。所以無論我用多少根手指頭在我的手機屏幕上比劃 也只會出現(xiàn)2個觸摸點,如下圖所示。
下面我們詳細的說一下代碼的實現(xiàn)方式,多點觸摸和單點觸摸一樣都是在onTouchEvent中去監(jiān)聽觸摸事件。調(diào)用方法event.getPointerCount(); 可以拿到當前屏幕同時觸摸點的數(shù)量 以我的手機為例因為只支持兩點觸摸所以在我的手機上調(diào)用該方法最多只會返回2。 拿到了觸摸屏幕點的數(shù)量以后 可以使用for循環(huán)來遍歷當前屏幕的所有觸摸點,調(diào)用event.getX(i); 與 event.getY(i); 方法 將ID作為參數(shù)傳入會得到每個點在屏幕中顯示的X Y坐標值。最后根據(jù)坐標值將圖片與內(nèi)容繪制在手機屏幕中。 - import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
import android.view.WindowManager;
import android.view.SurfaceHolder.Callback;
public class SurfaceViewAcitvity extends Activity {
MyView mAnimView = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 全屏顯示窗口
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// 顯示自定義的游戲View
mAnimView = new MyView(this);
setContentView(mAnimView);
}
public class MyView extends SurfaceView implements Callback {
/** 觸摸后繪制的圖片 **/
Bitmap mBitmap = null;
/** 游戲畫筆 **/
Paint mPaint = null;
SurfaceHolder mSurfaceHolder = null;
/** 控制游戲更新循環(huán) **/
boolean mRunning = false;
/** 游戲畫布 **/
Canvas mCanvas = null;
public MyView(Context context) {
super(context);
/** 設置當前View擁有控制焦點 **/
this.setFocusable(true);
/** 設置當前View擁有觸摸事件 **/
this.setFocusableInTouchMode(true);
/** 加載圖片 **/
mBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.item);
/** 拿到SurfaceHolder對象 **/
mSurfaceHolder = this.getHolder();
/** 將mSurfaceHolder添加到Callback回調(diào)函數(shù)中 **/
mSurfaceHolder.addCallback(this);
/** 創(chuàng)建畫布 **/
mCanvas = new Canvas();
/**創(chuàng)建畫筆**/
mPaint = new Paint();
mPaint.setColor(Color.WHITE);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
/** 拿到觸摸的狀態(tài) **/
int action = event.getAction();
/** 控制當觸摸抬起時清屏 **/
boolean reset = false;
switch (action) {
// 觸摸按下的事件
case MotionEvent.ACTION_DOWN:
Log.v("test", "ACTION_DOWN");
break;
// 觸摸移動的事件
case MotionEvent.ACTION_MOVE:
Log.v("test", "ACTION_MOVE");
break;
// 觸摸抬起的事件
case MotionEvent.ACTION_UP:
Log.v("test", "ACTION_UP");
reset = true;
break;
}
// 在這里加上線程安全鎖
synchronized (mSurfaceHolder) {
/** 拿到當前畫布 然后鎖定 **/
mCanvas = mSurfaceHolder.lockCanvas();
/** 清屏 **/
mCanvas.drawColor(Color.BLACK);
if (!reset) {
/** 在屏幕中拿到同時觸碰的點的數(shù)量 **/
int pointCount = event.getPointerCount();
/** 使用循環(huán)將每個觸摸點圖片都繪制出來 **/
for (int i = 0; i < pointCount; i++) {
/** 根據(jù)觸摸點的ID 可以講每個觸摸點的X Y坐標拿出來 **/
int x = (int) event.getX(i);
int y = (int) event.getY(i);
int showX = i * 150;
mCanvas.drawBitmap(mBitmap, x, y, mPaint);
mCanvas.drawText("當前X坐標:"+x, showX, 20, mPaint);
mCanvas.drawText("當前Y坐標:"+y, showX, 40, mPaint);
mCanvas.drawText("事件觸發(fā)時間:"+event.getEventTime(), showX, 60, mPaint);
}
}else {
mCanvas.drawText("請多點觸摸當前手機屏幕" ,0, 20, mPaint);
}
/** 繪制結(jié)束后解鎖顯示在屏幕上 **/
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
}
// return super.onTouchEvent(event);
return true;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
}
復制代碼 總體來說這章內(nèi)容還是比較簡單的,老規(guī)矩每篇文章都會附帶源代碼,最后如果你還是覺得我寫的不夠詳細 看的不夠爽 不要緊我把源代碼的下載地址貼出來 歡迎大家一起討論學習
第十三講-單點與多點觸摸.rar(125.29 KB, 下載次數(shù): 387)[/I]2011-9-3 00:51 上傳點擊文件名 下載積分: 下載豆 -2 |
上一篇: Android讀取彩信附件下一篇: Android 利用Java反射技術(shù)阻止通過按鈕關(guān)閉對話框
|