android遊戲開發(三)觸屏事件處理_手勢識別

 上一章 我們學習了 android 簡單的觸摸屏操作  那這一章我們來看看 android 的手勢操作  

 android的手勢識別是android更人性化,讓我們的操作更簡單, 其實我們日常應用中不少地方都使用了手勢識別方法  比如 2011年那麼火的 憤怒的小鳥 中的 發射武器, uc 遊覽器 的左右滑動功能,這都是可以使用android的手勢識別來實現。  

 

 如果想要實現提高我們app 的用戶體驗,更具有可操作性,那這時android的GestureDetector 就派上用場了 ,  我們先開看看GestureDetector這個類的api 給我們提供了哪些操作

下面是GestureDetector 這個類的概括情況

根據 MotionEvent事件檢測各種手勢. GestureDetector.OnGestureListener 回調函數用於通知用戶發生的手勢動作。該類僅處理 MotionEvent 事件中的觸摸事件(不處理軌跡球事件)。 使用該類的方法如下:

1:首先需要在初始化的時候創建GestureDetector對象實例

 

 

2:在View中的onTouchEvent方法中調用GestureDetector對象中的onTouchEvent方法當事件發生的時候就可以回調該方法

 

 

下面看看摘自android 的api 的摘要

interface GestureDetector.OnDoubleTapListener The listener that is used to notify when a double-tap or a confirmed single-tap occur. 
interface GestureDetector.OnGestureListener The listener that is used to notify when gestures occur. 
class GestureDetector.SimpleOnGestureListener A convenience class to extend when you only want to listen for a subset of all the gestures. 

 

 

 

現在我們來分析下GestureDetector這個類的概括情況  

 

 

接口 OnDoubleTapListener   手勢監聽器  用於雙擊時發出通知

接口 OnGestureListener     手勢監聽器 用於發送手勢操作時發生通知 如 拖動,長按,按下,彈起 等手勢操作

類   SimpleOnGestureListener    GestureDetector的擴展類  這個類的作用是當我們只想使用部分手勢時, 而非全部的時候 就可以繼承這個類

GestureDetector 還有幾個公共方法 如下

boolean isLongpressEnabled()  判定是否允許長點擊
boolean onTouchEvent(MotionEvent ev)
分析給定的動作事件,如果滿足條件,就觸發GestureDetector.OnGestureListener 中提供的回調函數。
void setIsLongpressEnabled(boolean isLongpressEnabled)
設置是否允許長按。如果允許長按,當用戶按下並保持按下狀態時, 將收到一個長按事件,同時不再接收其它事件;如果禁用長按, 當用戶按下並保持按下狀態然後再移動手指時,將會接收到滾動事件。 長按默認爲允許。
void setOnDoubleTapListener(GestureDetector.OnDoubleTapListener onDoubleTapListener)
設置雙擊及其相關手勢的監聽器。

  

OnGestureListener 接口 的公共方法  如果你想在你的app view中實現下面這些手勢操作的話 繼承該接口 並實現下面這些方法即可

abstract boolean onDown(MotionEvent e)
當輕觸手勢按下屏幕 時發生的事件.
abstract boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
快速滑動後擡起事件的通知.
abstract void onLongPress(MotionEvent e)
長按時的通知事件
abstract boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
滑動屏幕時通知事件 爲了方便提供了X軸和Y軸上的滾動距離.
abstract void onShowPress(MotionEvent e)
當用戶長點擊後擡起時通知事件
abstract boolean onSingleTapUp(MotionEvent e)
當輕觸手勢擡起屏幕時發生的事件.

OnDoubleTapListener 接口的公共方法 

abstract boolean onDoubleTap(MotionEvent e)
雙擊發生時的通知。
abstract boolean onDoubleTapEvent(MotionEvent e)
雙擊手勢過程中發生的事件,包括按下、移動和擡起事件。
abstract boolean onSingleTapConfirmed(MotionEvent e)
發生確定的單擊時執行。

onSingleTapUp(MotionEvent)不同, 該事件在探測器確定用戶單擊後沒有發生導致雙擊事件的第二次單擊時發生。

在實際應用中 我們根據我們所需要的功能實現不同的接口 或者 繼承自SimpleOnGestureListener 類 只實現部分個人需要的方法 就可以了

我們這一章就以  OnGestureListener 接口來做示例 看看 他是怎麼使用的

 直接看代碼 GameSurfaceView類

 

package yxqz.com;


import android.content.Context;

import android.content.DialogInterface;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.graphics.Canvas;

import android.graphics.Color;

import android.util.Log;

import android.view.GestureDetector;

import android.view.GestureDetector.OnGestureListener;

import android.view.MotionEvent;

import android.view.SurfaceHolder;

import android.view.SurfaceView;

import android.view.SurfaceHolder.Callback;

import android.widget.Toast;


/**

 * android 手勢識別

 * @author mahaile

 *

 */

public class GameSurfaceView extends SurfaceView implements Callback,OnGestureListener{


private String TAG="GameView";


boolean flag; //線程標示位 當爲false時停止刷新界面

SurfaceHolder surfaceHolder;

GameViewThread gameViewThread;

float x=0,y=0;

int stat=0;  //手勢識別狀態標示

private GestureDetector gd; // 手勢

Context context;

int width,height;

Bitmap bitmap_role;

public GameSurfaceView(Context context) {

super(context);

this.context=context;

surfaceHolder=this.getHolder();

surfaceHolder.addCallback(this); //添加回調

//設置焦點 如果不設置焦點的話 在該界面下 點擊觸摸屏是無效的 默認爲false

setFocusableInTouchMode(true);

bitmap_role=BitmapFactory.decodeResource(getResources(), R.drawable.role);

gd=new GestureDetector(this);   //創建手勢監聽對象

}

public void onDraw(Canvas canvas){

canvas.drawColor(Color.BLACK);

//canvas.drawBitmap(bitmap_role, width/2-bitmap_role.getWidth()/2, y, null);

canvas.drawBitmap(bitmap_role, x-bitmap_role.getWidth()/2, y-bitmap_role.getHeight()/2, null);

}

    //重寫父類中的 onTouchEvent就可以監聽到  觸摸事件了 記住要設置焦點喔 

@Override

public boolean onTouchEvent(MotionEvent event) {

gd.onTouchEvent(event); //通知手勢識別方法 

return true;

}

public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {

}


public void surfaceCreated(SurfaceHolder surfaceHolder) {

//獲取屏幕的 寬高 只有在 surface創建的時候 纔有效 ,才構造方法中獲取 寬高是獲取不到的

width=this.getWidth();

height=this.getHeight();

//初始化繪圖線程

gameViewThread=new GameViewThread();

gameViewThread.flag=true;

gameViewThread.start();

}


public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

gameViewThread.flag=false; //銷燬線程

}


class GameViewThread extends Thread{

public boolean flag;

public void run(){

while(flag){

Canvas canvas=null;

try{

canvas=surfaceHolder.lockCanvas(); //鎖定畫布 並獲取canvas

onDraw(canvas);//調用onDraw 渲染到屏幕

surfaceHolder.unlockCanvasAndPost(canvas); //此步不要忘記了喔 否則界面上顯示不出來的

}catch(Exception e){

e.printStackTrace();

}

try {

Thread.sleep(10);//線程休眠時間  控制幀數

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}  //每一秒刷新一次

}

}

}

 

    //**************************下面是手勢識別的重寫方法*******************************************

//屏幕點下

public boolean onDown(MotionEvent arg0) {

Log.d(TAG, "onDown");

Toast.makeText(this.context, "你點擊了屏幕", Toast.LENGTH_SHORT).show();

return false;

}

//屏幕點下

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,

float velocityY) {

Log.d(TAG, "onFling");

Toast.makeText(this.context, "你拖動屏幕後彈起", Toast.LENGTH_SHORT).show();

return false;

}

   //屏幕點下 並長按時觸發

public void onLongPress(MotionEvent e) {

Log.d(TAG, "onLongPress");

Toast.makeText(this.context, "你長按了屏幕", Toast.LENGTH_SHORT).show();

}

    //屏幕拖動

public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,

float distanceY) {

this.x=this.x-distanceX;

this.y=this.y-distanceY;

Toast.makeText(this.context, "你拖動了屏幕", Toast.LENGTH_SHORT).show();

return false;

}

   //屏幕長按

public void onShowPress(MotionEvent e) {

// TODO Auto-generated method stub

Toast.makeText(this.context, "你長按屏幕後彈起", Toast.LENGTH_SHORT).show();

Log.d(TAG, "onShowPress");

}

   //屏幕點擊後彈起

public boolean onSingleTapUp(MotionEvent e) {

   Log.d(TAG, "onSingleTapUp");

   Toast.makeText(this.context, "你彈起屏幕", Toast.LENGTH_SHORT).show();

return false;

}

}

有一點大家需要注意一下 每次執行手勢時 可以會執行多個手勢通知 大家需要留意一下喔,避免重複操作app邏輯

上面的代碼中 紅色部分標示了 手勢識別的主要部分  大家趕快加到自己的app 裏面吧 讓自己的app 更有吸引力  其他兩種種方式 和這種很類似,各位童鞋可以自己試試喔 


在後續的過程中 我們會有一章 遊戲地圖 介紹  的章節 , 那時我們使用手勢識別來拖動地圖

 

歡迎各位童鞋 來拍磚喔,,有啥不懂的地方留言給我喔 一起學習 共同進步  加油 。。

下面是源碼地址 

http://download.csdn.net/detail/ma_haile/4221223


 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章