上一章 我們學習了 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 的摘要
GestureDetector.OnDoubleTapListener | The listener that is used to notify when a double-tap or a confirmed single-tap occur. | |
GestureDetector.OnGestureListener | The listener that is used to notify when gestures occur. | |
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 還有幾個公共方法 如下
分析給定的動作事件,如果滿足條件,就觸發
GestureDetector.OnGestureListener 中提供的回調函數。 |
|
設置是否允許長按。如果允許長按,當用戶按下並保持按下狀態時, 將收到一個長按事件,同時不再接收其它事件;如果禁用長按, 當用戶按下並保持按下狀態然後再移動手指時,將會接收到滾動事件。 長按默認爲允許。
|
|
設置雙擊及其相關手勢的監聽器。
|
OnGestureListener 接口 的公共方法 如果你想在你的app view中實現下面這些手勢操作的話 繼承該接口 並實現下面這些方法即可
當輕觸手勢按下屏幕 時發生的事件.
|
|
快速滑動後擡起事件的通知.
|
|
長按時的通知事件
|
|
滑動屏幕時通知事件 爲了方便提供了X軸和Y軸上的滾動距離.
|
|
當用戶長點擊後擡起時通知事件
|
|
當輕觸手勢擡起屏幕時發生的事件.
|
OnDoubleTapListener 接口的公共方法
雙擊發生時的通知。
|
|
雙擊手勢過程中發生的事件,包括按下、移動和擡起事件。
|
|
發生確定的單擊時執行。
與 |
在實際應用中 我們根據我們所需要的功能實現不同的接口 或者 繼承自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