本系列文章均為A2BGeek原創,轉載務必在明顯處注明:
轉載自A2BGeek的【Android每周專題】系列,原文鏈接:
http://blog.csdn.net/benbmw2008/article/details/11367631
這篇專題來研究一下Android的觸摸屏手勢Gesture,Android的手勢有兩種,一種是View和Activity的(基于觸摸屏事件,所以Activity也能添加手勢),一種是手寫輸入法或者一些手機瀏覽器的快捷手勢那樣的帶筆跡的手勢識別。這一點從API文檔中就能體現出來:分別有android.view.GestureDetector和android.gesture.Gesture。
我們先來介紹View和Activity的手勢,再介紹輸入法手勢識別。
View和Activity的手勢
拋擲(onFling): 手指在觸摸屏上迅速移動,并松開的動作。
長按(onLongPress): 手指按在持續一段時間,并且沒有松開。
滾動(onScroll): 手指在觸摸屏上滑動。
按住(onShowPress): 手指按在觸摸屏上,它的時間范圍在按下起效,在長按之前。
抬起(onSingleTapUp):手指離開觸摸屏的那一剎那。
除了這些定義之外,鄙人也總結了一點算是經驗的經驗吧,在這里和大家分享一下。
任何手勢動作都會先執行一次按下(onDown)動作。
長按(onLongPress)動作前一定會執行一次按住(onShowPress)動作。
按住(onShowPress)動作和按下(onDown)動作之后都會執行一次抬起(onSingleTapUp)動作。
長按(onLongPress)、滾動(onScroll)和拋擲(onFling)動作之后都不會執行抬起(onSingleTapUp)動作。
package com.example.gesturedemo; import android.content.Context; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.GestureDetector.OnGestureListener; import android.view.MotionEvent; import android.widget.TextView; public class MyTextView extends TextView implements OnGestureListener { private GestureDetector mGestureDetector; public MyTextView(Context context) { super(context); // TODO Auto-generated constructor stub mGestureDetector = new GestureDetector(context, this); } public MyTextView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub mGestureDetector = new GestureDetector(context, this); } public MyTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub mGestureDetector = new GestureDetector(context, this); } @Override public boolean dispatchTouchEvent(MotionEvent event) { // TODO Auto-generated method stub DebugTool.log("MyTextView--->dispatchTouchEvent"); return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub DebugTool.log("MyTextView--->onTouchEvent"); // int action = event.getAction(); // switch (action) { // case MotionEvent.ACTION_DOWN: // DebugTool.log("MyTextView--->onTouchEvent--->DOWN"); // break; // case MotionEvent.ACTION_MOVE: // DebugTool.log("MyTextView--->onTouchEvent--->MOVE"); // break; // case MotionEvent.ACTION_UP: // DebugTool.log("MyTextView--->onTouchEvent--->UP"); // break; // } return mGestureDetector.onTouchEvent(event); } @Override public boolean onDown(MotionEvent e) { // TODO Auto-generated method stub return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // TODO Auto-generated method stub DebugTool.log("MyTextView--->onFling"); return false; } @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // TODO Auto-generated method stub return false; } @Override public void onShowPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onSingleTapUp(MotionEvent e) { // TODO Auto-generated method stub return false; } }
在OnGestureListener的帶返回值的幾個回調方法默認返回false的情況下,你會發現Fling手勢是識別不到的,這是什么原因呢?這需要用上一專題的知識來解釋 http://blog.csdn.net/benbmw2008/article/details/11143893 。 大家應該能看出來手勢是基于觸摸屏事件傳遞的,對照著上一篇的“默認事件流向”圖,讀者可以想象其實就是在“MyTextView onTouchEvent”和“MyRelativeLayout onTouchEvent”之間加一個"MyTextView's GestureDetector onTouchEvent",而"MyTextView's GestureDetector onTouchEvent"返回false,事件還是會繼續傳遞給“MyRelativeLayout onTouchEvent”。 解決的辦法是什么呢?自然是把OnGestureListener的帶返回值的幾個回調方法返回true,這樣觸摸屏事件就被“GestureDetector onTouchEvent”所消費,看一下日志會更加清楚:
09-08 10:36:10.718: V/gesturedemo(13130): MyRelativeLayout--->dispatchTouchEvent
09-08 10:36:10.722: V/gesturedemo(13130): MyRelativeLayout--->onInterceptTouchEvent
09-08 10:36:10.722: V/gesturedemo(13130): MyTextView--->dispatchTouchEvent
09-08 10:36:10.722: V/gesturedemo(13130): MyTextView--->onTouchEvent
09-08 10:36:10.824: V/gesturedemo(13130): MainActivity--->dispatchTouchEvent
09-08 10:36:10.828: V/gesturedemo(13130): MyRelativeLayout--->dispatchTouchEvent
09-08 10:36:10.832: V/gesturedemo(13130): MyRelativeLayout--->onInterceptTouchEvent
09-08 10:36:10.835: V/gesturedemo(13130): MyTextView--->dispatchTouchEvent
09-08 10:36:10.835: V/gesturedemo(13130): MyTextView--->onTouchEvent
09-08 10:36:10.863: V/gesturedemo(13130): MainActivity--->dispatchTouchEvent
09-08 10:36:10.878: V/gesturedemo(13130): MyRelativeLayout--->dispatchTouchEvent
09-08 10:36:10.886: V/gesturedemo(13130): MyRelativeLayout--->onInterceptTouchEvent
09-08 10:36:10.886: V/gesturedemo(13130): MyTextView--->dispatchTouchEvent
09-08 10:36:10.886: V/gesturedemo(13130): MyTextView--->onTouchEvent
09-08 10:36:10.898: V/gesturedemo(13130): MainActivity--->dispatchTouchEvent
09-08 10:36:10.898: V/gesturedemo(13130): MyRelativeLayout--->dispatchTouchEvent
09-08 10:36:10.898: V/gesturedemo(13130): MyRelativeLayout--->onInterceptTouchEvent
09-08 10:36:10.898: V/gesturedemo(13130): MyTextView--->dispatchTouchEvent
09-08 10:36:10.898: V/gesturedemo(13130): MyTextView--->onTouchEvent
09-08 10:36:10.917: V/gesturedemo(13130): MainActivity--->dispatchTouchEvent
09-08 10:36:10.917: V/gesturedemo(13130): MyRelativeLayout--->dispatchTouchEvent
09-08 10:36:10.917: V/gesturedemo(13130): MyRelativeLayout--->onInterceptTouchEvent
09-08 10:36:10.917: V/gesturedemo(13130): MyTextView--->dispatchTouchEvent
09-08 10:36:10.917: V/gesturedemo(13130): MyTextView--->onTouchEvent
09-08 10:36:10.917: V/gesturedemo(13130): MyTextView--->onFling
輸入法手勢識別
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/tv1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:text="@string/hello_world" android:textSize="24sp" /> <android.gesture.GestureOverlayView android:id="@+id/gestures" android:layout_width="200dip" android:layout_height="200dip" android:layout_centerInParent="true" android:background="#33B5E5" > </android.gesture.GestureOverlayView> </RelativeLayout>
代碼如下:
package com.a2bgeek.gesturedemo2; import java.util.ArrayList; import android.os.Bundle; import android.app.Activity; import android.gesture.Gesture; import android.gesture.GestureLibraries; import android.gesture.GestureLibrary; import android.gesture.GestureOverlayView; import android.gesture.GestureOverlayView.OnGesturePerformedListener; import android.gesture.Prediction; import android.view.Menu; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { private TextView mTextView; private GestureOverlayView mGestureOverlayView; private GestureLibrary mGestureLibrary; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initViews(); } private void initViews() { mTextView = (TextView) findViewById(R.id.tv1); mGestureLibrary = GestureLibraries.fromRawResource( getApplicationContext(), R.raw.gestures); if (mGestureLibrary.load()) { mGestureOverlayView = (GestureOverlayView) findViewById(R.id.gestures); mGestureOverlayView .addOnGesturePerformedListener(new MyGesturePerformListener()); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } private class MyGesturePerformListener implements OnGesturePerformedListener { @Override public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) { // TODO Auto-generated method stub ArrayList<Prediction> list = mGestureLibrary.recognize(gesture); if (list.size() > 0) { //list是mGestureLibrary中可能與gesture匹配的手勢集,匹配的程度會有一個score評分。 StringBuilder sb = new StringBuilder(); for (Prediction prediction : list) { sb.append(prediction.name); sb.append(":"); sb.append(prediction.score); sb.append("\n"); } mTextView.setText(sb.toString()); } else { Toast.makeText(getApplicationContext(), "沒有匹配", Toast.LENGTH_SHORT).show(); } } } }

更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
