Gestures(手勢)
本節引言:
#週六不休息,剛剪完了個大平頭回來,繼續碼字~
好的,本節帶給大家點的是第三章的最後一節-Gestures(手勢), 用過魅族手機的朋友相信對手勢肯定是不陌生的,在home鍵兩側像螢幕內滑動, 可以開啟後台任務清單等等~在應用程式中透過手勢來操作會大大提升使用者體驗, 例如Scroll手勢在瀏覽器中滾屏,Fling在瀏覽器中的換頁等!
當然,有利也有弊,例如不當的手勢操作引起APP Carsh,經常這樣可是會引起用戶不滿的! 所以是否要為你的應用程式增加手勢,可要考慮清楚哦!另外手勢要跟前面學的單指/多指觸碰相區分哦!
手勢是:連續觸碰的行為,例如左右上下滑動螢幕,又或者畫一些不規則的幾何圖形! Android對上述兩種手勢行為都提供了支援:
- Android提供手勢偵測,並為手勢辨識提供了相應的監聽器!
- Android運行開發者自行加入手勢,並且提供了對應的API辨識使用者手勢!
如果你的手機是Android 4.x的原生Android系統的話,你可能可以在你的手機或平板上看到谷歌 提供的一個Gesture Builder的APP,該應用程式允許使用者以類似於塗鴉的方式繪製一個手寫符號,使之 對應一個字串名稱!當然,沒有這樣的手機也沒關係,我們有模擬器嘛,自己開4.0的系統試試 就知道了,另外,我們可以到\mmt\sdcard\gestures取得到保存手勢的檔案! 好了,嘮叨那麼多,開始講正題吧!
對了,貼上官方API文件先:GestureDetector
#1.Android中手勢互動的執行順序
- 1.手指觸碰螢幕時,觸發MotionEvent事件!
- 2.該事件被OnTouchListener監聽,可在它的onTouch()方法中獲得該MotionEvent物件!
- 3.透過GestureDetector轉發MotionEvent物件給OnGestureListener
- 4.我們可以透過OnGestureListener取得該對象,然後取得相關訊息,以及做相關處理!
我們來看下上述的三個類別都是幹嘛的:MotionEvent: 這個類別用來封裝手勢、觸控筆、軌跡球等等的動作事件。 其內部封裝了兩個重要的屬性X和Y,這兩個屬性分別用來記錄橫軸和縱軸的座標。 GestureDetector: 辨識各種手勢。 OnGestureListener: 這是一個手勢互動的監聽接口,其中提供了多個抽象方法, 並根據GestureDetector的手勢辨識結果呼叫相對應的方法。
-上述資料摘自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1020/448.html
#2.GestureListener詳解:
從1我們知道了監聽手勢的關鍵是:GestureListener 他給我們提供了下述的回調方法:
- 按下(onDown): 剛剛手指接觸到觸控螢幕的那一剎那,就是觸的那一下。
- 拋擲(onFling): 手指在觸控螢幕上迅速移動,並鬆開的動作。
- 長按(onLongPress): 手指按在持續一段時間,且沒有放開。
- 滾動(onScroll): 手指在觸控螢幕上滑動。
- 按住(onShowPress): 手指按在觸控螢幕上,它的時間範圍在按下起效,在長按之前。
- 抬起(onSingleTapUp):手指離開觸控螢幕的那一剎那。
知道了GestureListener的相關方法後,實作手勢偵測也很簡單,步驟如下:
- Step 1: 建立GestureDetector對象,創建時需實作GestureListener傳入
- Step 2: 將Activity或特定元件上的TouchEvent的事件交給GestureDetector處理即可! 我們寫個簡單的程式碼來驗證這個流程,也就是重寫對應的方法:
程式碼如下:
私有MyGestureListener mgListener;
# GestureDetector mDetector @ Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedIn” //實例化GestureListener與GestureDetector物件
mgListener = new MyGestureListener();
mDetector = new GestureDetector(this, mgListener);
} {
return mDetector. onTouchEvent (event);
}
//自訂一個GestureListener,這是在View類別下的,別寫錯誤! ## @Override
public boolean onDown(MotionEvent motionEvent) {
return false;
}
@Override
public void onShowPress(MotionEvent motionEvent) {
}
@Override
public boolean onSingleTapUp(MotionEvent motionEvent) {
return false;
}
#@Override
public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, f 滑");
return false;
}
@Override
# public void onLongPress(MotionEvent motion );
}
@Override
public boolean onFling(MotionEvent motionEvent, MotionEvent motion#1, Log.d(TAG, "onFling:迅速滑動,並鬆開");
return false;
}
}
}
對應操作截圖:
1.按下後立即放開:
- ##2.長按後放開:
- 3.輕輕一滑,同時放開:
4.按住後不放持續做滑動操作:
PS:從上述結果來看,我們發現了一個問題: 我們實作OnGestureListener需要實現所有的手勢,可能我針對的只是滑動,但你還是要去重載, 這顯得很逗逼,對吧,官方肯定會給出解決方法滴,官方另外給我們提供了一個SimpleOnGestureListener類 只要把上述的OnGestureListener替換成SimpleOnGestureListener即可!
3.簡單的例子:下滑關閉Activity,上滑啟動新的Activity這裡就用上述的SimpleOnGestureListener來實現吧:
#執行效果圖:################實作程式碼:#######
private GestureDetector mDetector;
private#final mDetector;
private#final static private MyGestureListener mgListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
main);
//實例化SimpleOnGestureListener與GestureDetector物件
mgListener = new MyGestureListener();
mDetector = new Gesture遠
mgListList public boolean onTouchEvent(MotionEvent event) {
return mDetector .onTouchEvent(event);
}
//自訂一個GestureListener,這個是View類別下的,別寫錯喔! ! !
private class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
, float v, float v1) {
if(e1.getY() - e2.getY() > MIN_MOVE){
startActivity(new Intent(MainActivity.約makeText(MainActivity.this, "透過手勢啟動Activity", Toast.LENGTH_SHORT) .show();
}else if(e1.getY() - e2.getY() < MIN_MOVE Toast.makeText(MainActivity.this,"透過手勢關閉Activity",Toast.LENGTH_SHORT).show();
}
回傳 true;
}
}
}
結果分析:從上面的比較就可以知道,比起SimpleOnGestureListener使用SimpleOnGestureListener 顯得更加的簡單,想重寫什麼方法就重寫什麼方法,另外例子比較簡單,大家可以自己試試 其他玩法,例如透過手勢縮放圖片~
4.手勢添加與識別:
除了上面講解的手勢檢測外,Android還運行我們將手勢進行添加,然後提供了相關的識別API; Android中使用GestureLibrary來代表手勢庫,提供了GestureLibraries工具類別來建立手勢庫!
四個載入手勢庫的靜態方法:
獲得GestureLibraries物件後,就可以使用該物件提供的下述方法來做對應操作了:
相關方法:
- public void addGesture (String entryName, Gesture gesture):新增一個名為entryName的手勢
- public Set<String> getGestureEntries ():取得手勢庫中所有手勢的名稱
- public ArrayList<Gesture> getGestures (String entryName) :取得entryName名稱對應的全部手勢
- public ArrayList<Prediction> recognize (Gesture gesture): 從目前手勢庫中辨識與gesture相符的全部手勢
- public void removeEntry (String entryName):刪除手勢庫中entryName名稱對應的手勢
- public void removeGesture (String entryName, Gesture gesture):刪除手勢庫中entryName和gesture都匹配的手勢
- public abstract boolean save ():想手勢庫中添加手勢或從中刪除手勢後調用該方法保存手勢庫
#GestureOverlayView手勢編輯元件:
Android為GestureOverlayView提供了三種監聽器接口,如下,一般常用的是:OnGesturePerformedListener;用於手勢完成時提供響應!
5.手勢新增範例:
PS:範例引用的是-李剛《Android瘋狂講義》的程式碼
##在運行效果圖:
好吧,下面貼上實作程式碼:兩個佈局檔案:activity_main.xml和dialog_save. xmlactivity_main.xml
#
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="結;TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"# android:textSize="20sp"/ >
<!-- gestureStrokeType控製手勢是否需要完成,multiple表示允許多筆-->
<android.ges.GestureOverlay ## <android. ="@+id/gesture"
android:layout_width="match_parent"
android:layout_height="match_parent"##> #</ LinearLayout>
#
dialog_save.xml
android:layout_height="match_parent"
# android:layout_width="match_parent"
android:layout_height="wrap_content"
Text View
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_width= "match_parent"
android:layout_height="wrap_content"
android:id="@+id/edit_name"/>
img_show"
android:layout_width="128dp"
android:layout_height="128dp"## out>
MainActivity.java:
私有EditText editText;
# 私有GestureOverlayView 手勢;
# .S. # # super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);# = (GestureOverlayView) findViewById(R.id.gesture ) ;
gesture.setGestureColor(Color.GREEN);
gesture.setGestureStrokeWidth(5);#116> turePerformedListener() {
@Override
public void onGesturePerformed( GestureOverlayView gestureOverlayView,最終手勢){
View saveDialog = getLayoutInflater ImageView img_show = (ImageView) saveDialog.findViewById(R.id.img_顯示);
最終 EditText edit_name = (EditText) saveDialog.find圖 bitmap = gesture.toBitmap(128,128,10,0xffff0000);
img_show.setImageBitmap(ImageBitmap( );
new AlertDialog.Builder(MainActivity.this).setView(saveDialog)
tton("保存",new DialogInterface.OnClickListener()
{
# @Override
public 所寫 //使用文件的實驗室
gestureLib = GestureLibraries.fromFile("/mnt/sdcard/mygestures");
gestureLib .addGesture(edit_name.getText().toString(),gesture);
}
# }
});
}
}
最後也需要在AndroidManifest.xml中加入寫入SD卡的權限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
6.手勢辨識範例
實作程式碼:
private GestureOverlayView gesture;
@Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
set ## gestureLibrary = GestureLibraries.fromFile("mmt/sdcard/ mygestures");
if (gestureLibrary.load()) {
Toast } else {
Toast.makeText(mContext, "手勢庫載入失敗", Toast.LENGTH_SHORT).show();
}
tureOverlayView ) findViewById(R.id.gesture);
gesture.setGestureColor(Color.GREEN);
(new GestureOverlayView.OnGesturePerformedListener() {
@ Override
public void onGesturePerformed(GestureOverlayView gestureOverlayView, final Gesture /1# ## ArrayList<Prediction> predictions = gestureLibrary.recoan result = new ArrayList<String>();
//遍歷中所找到的Prediction物件
#for (Prediction pred : predictions) {
result.add("與手勢【" + pred.name + "】相似度為" + pred.score);
}
ize() > 0) {
以ArrayAdapter< android.R.layout.simple_dropdown_item_1line , result.toArray());
new AlertDialog.. }else{
Toast. makeText(mContext,"無法找到匹配的手勢!",Toast.LENGTH_SHORT).show();
}# # }
另外別忘了在AndroidManifest.xml檔案中加入讀取SD卡的權限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
本節小結: