Android基本功:手勢


一、概念 

  • 手勢:其實是指用戶手指或觸摸筆在屏幕上的連續觸碰行為,Andoird對兩種手勢行為都提供了支持 

    • Andorid提供了手勢檢測,並為手勢檢測提供了相應的監聽器 

    • Android允許開發者添加手勢,並提供了相應的API識別用戶手勢 

     

二、手勢檢測 

  • Gesture類:代表了一個手勢檢測器 

  • GestureDectector.OnGestureListener類:代表一個監聽器、負責對用戶的手勢行為提供響應 

    • boolean onDown(MotionEvent e):當觸碰事件按下時觸發的方法 

    • boolean onFling(MotionEvent e1,MotionEvent e2,float velocityX,float velocityY):當用戶在觸摸屏上”拖過”時觸發該方法,velocityX,velocityY代表“拖過”動作的橫向、縱向上的速度 

    • abstract void onLongPress(MotionEvent e):當用戶在屏幕上長按時觸發該方法 

    • abstract void onScroll(MotionEvent e1,MotionEvent e2,float distanceX,float diastanceY):當用戶在屏幕上“滾動”時觸發該方法 

    • void onShowPress(MotionEvent e):當用戶在屏幕上按下,而且還未移動和松動的時候觸發該方法 

    • boolean onSingleTapUp(MotionEvent e):當用戶在觸摸屏上的輕擊事件將會觸發該方法 

 

三、使用步驟 

  1. 創建一個GestureDetector對象,創建對象時候必須創建一個GestureDectector.OnGestureListener監聽器實例; 

  2. 為應用程序的Activity(偶爾也可以為特定組件)的TouchEvent事件綁定監聽器,在事件處理中制定把Activity(或特定組件)上的TouchEvent事件交給GestureDetector處理; 

 

  • 使用實例(chapter08/GestureTest 

MainActivity.java文件  

  1. public class MainActivity extends Activity implements OnGestureListener {   
  2.     // 定義手勢檢測實例   
  3.     GestureDetector detector;   
  4.    
  5.     @Override   
  6.     protected void onCreate(Bundle savedInstanceState) {   
  7.         super.onCreate(savedInstanceState);   
  8.         setContentView(R.layout.main_activity);   
  9.    
  10.         // 創建手勢檢測器   
  11.         detector = new GestureDetector(thisthis);   
  12.     }   
  13.    
  14.     @Override   
  15.     public boolean onTouchEvent(MotionEvent event) {   
  16.         // 將該Activity上的觸碰事件交給GestureDetector處理   
  17.         return detector.onTouchEvent(event);   
  18.     }   
  19.    
  20.     @Override   
  21.     public boolean onDown(MotionEvent e) {   
  22.          // 觸碰時間按下時觸發該方法   
  23.         Toast.makeText(this"OnDown", Toast.LENGTH_LONG).show();   
  24.         return false;   
  25.     }   
  26.    
  27.     @Override   
  28.     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,   
  29. float velocityY) {   
  30.          // 當用戶在屏幕上“拖動”時觸發該方法   
  31.         Toast.makeText(this"onFling", Toast.LENGTH_LONG).show();   
  32.         return false;   
  33.     }   
  34.    
  35.     @Override   
  36.     public void onLongPress(MotionEvent e) {   
  37.         // 當用戶在屏幕上長按時觸發該方法   
  38.         Toast.makeText(this"onLongPress", Toast.LENGTH_LONG).show();   
  39.     }   
  40.    
  41.     @Override   
  42.     public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,   
  43. float distanceY) {   
  44.         // 當屏幕“滾動”時觸發該方法   
  45.         Toast.makeText(this"onScroll", Toast.LENGTH_LONG).show();   
  46.         return false;   
  47.     }   
  48.    
  49.     @Override   
  50.     public void onShowPress(MotionEvent e) {   
  51.         // 當用戶在觸摸屏幕上按下、而且還未移動和松開時觸發該方法   
  52.         Toast.makeText(this"onShowPress", Toast.LENGTH_LONG).show();   
  53.     }   
  54.    
  55.     @Override   
  56.     public boolean onSingleTapUp(MotionEvent e) {   
  57.         // 在屏幕上的輕擊事件將會觸發該方法   
  58.        Toast.makeText(this"onSingleTapUp", Toast.LENGTH_LONG).show();   
  59.         return false;   
  60.     }   
  61. }   

 

四、增加手勢 

  • Android除了提供了手勢之外,還允許應用程序把用戶手勢(多個持續的觸摸事件在屏幕上形成特定的形狀)添加到制定文件中,以備以后使用; 

  • GestureLibrary類:代表手勢庫,並提供了GestureLibraries工具來創建手勢庫,提供了如下4個靜態方法從不同的位置加載手勢: 

    • static GestureLibrary from(String path):從path代表的文件中加載手勢庫 

    • static GestureLibrary fromFile(File path):從path代表的文件加載手勢庫 

    • static GestureLibrary fromPrivateFile(Context context,String name):從制定應用程序的數據文件夾中name文件中加載手勢庫 

    • static GestureLibrary fromRawResoure(Context context,int resourceId):從resourceId所代表的資源中加載手勢庫 

 

  • 獲取GestureLibrary對象之后,該對象提供了如下方法來添加手勢和識別手勢 

    • void addGesture(String entryName,Gesture gesture):添加一個名為name的手勢 

    • Set<String> getGestureEntries():獲取手勢庫中所有的手勢名稱 

    • ArrayList<GuesturegetGestures(String entryName):獲取entryName名稱對應的全部手勢 

    • ArrayList<Prediction> recongize(Guesture gesture):從當前手勢庫中識別與gesture匹配的全部手勢 

    • void removeEntry(String entryName):刪除手勢庫中entryName對應的手勢 

    • void removeGesture(String entryName,Gesture gesture):刪除手勢庫中entryName,gesture對應的手勢庫 

    • boolean save():當向手勢庫中添加手勢或從中刪除手勢后調用該方法保存手勢庫 

 

  • 為了監聽GestureOverlayView組件上的手勢事件,Android為GestureOverlayView提供了OnGestureLisnter、OnGesturePerformedListener、OnGesturingListener三個監聽器接口,分別用於響應手勢事件開始、結束、完成、取消事件; 

     

  • 使用實例(chapter08/AddGesture 

main_activity.xml文件  

  1. <?xml version="1.0" encoding="utf-8"?>   
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"   
  3.     android:layout_width="match_parent"   
  4.     android:layout_height="match_parent"   
  5.     android:orientation="vertical" >   
  6.     <TextView   
  7.         android:layout_width="match_parent"   
  8.         android:layout_height="wrap_content"   
  9.         android:gravity="center_horizontal"   
  10.         android:text="請在下面屏幕上繪制手勢" />   
  11.     <!-- android:gestureStrokeType手勢是否需要一筆完成-->   
  12.     <android.gesture.GestureOverlayView   
  13.         android:id="@+id/gesture"   
  14.         android:layout_width="match_parent"   
  15.         android:layout_height="match_parent"   
  16.         android:gestureStrokeType="multiple" />   
  17. </LinearLayout>   
 

 

sava.xml文件  

  1. <?xml version="1.0" encoding="utf-8"?>   
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"   
  3.     android:layout_width="match_parent"   
  4.     android:layout_height="match_parent"   
  5.     android:orientation="vertical" >   
  6.     <LinearLayout   
  7.         android:layout_width="match_parent"   
  8.         android:layout_height="wrap_content"   
  9.         android:orientation="horizontal" >   
  10.         <TextView   
  11.             android:layout_width="wrap_content"   
  12.             android:layout_height="wrap_content"   
  13.             android:layout_marginRight="8dip"   
  14.             android:text="請輸入手勢名稱" />   
  15.         <!-- 定義一個文本框讓用戶輸入手勢名 -->   
  16.         <EditText   
  17.             android:id="@+id/gesture_name"   
  18.             android:layout_width="match_parent"   
  19.             android:layout_height="wrap_content" />   
  20.     </LinearLayout>   
  21.     <!-- 定義一個圖片框來顯示手勢 -->   
  22.     <ImageView   
  23.         android:id="@+id/show"   
  24.         android:layout_width="match_parent"   
  25.         android:layout_height="128dp"   
  26.         android:layout_marginTop="10dp"   
  27.         android:layout_weight="0.29" />   
  28. </LinearLayout>   
 

 

MainActivity.java文件  

  1. public class MainActivity extends Activity {   
  2.     EditText editText;   
  3.     GestureOverlayView gestureOverlayView;   
  4.    
  5.     @Override   
  6.     protected void onCreate(Bundle savedInstanceState) {   
  7.         super.onCreate(savedInstanceState);   
  8.         setContentView(R.layout.main_activity);   
  9.    
  10.         // 使用文本編輯器   
  11.         editText = (EditText) findViewById(R.id.gesture_name);   
  12.         // 獲取手勢編輯視圖   
  13.         gestureOverlayView = (GestureOverlayView) findViewById(R.id.gesture);   
  14.         // 設置手勢繪圖的顏色   
  15.         gestureOverlayView.setGestureColor(Color.RED);   
  16.         // 設置手勢的繪制寬度   
  17.         gestureOverlayView.setGestureStrokeWidth(4);   
  18.         // 為gesture的手勢完成事件綁定事件監聽器   
  19.         gestureOverlayView.addOnGesturePerformedListener(new OnGesturePerformedListener() {   
  20.    
  21.         @Override   
  22.         public void onGesturePerformed(GestureOverlayView overlay,final Gesture gesture) {   
  23.             // 加載save.xml界面布局代表的視圖   
  24.             View saveDialog = getLayoutInflater().inflate(R.layout.save, null);   
  25.             // 獲取saveDialog里的show組件   
  26.             ImageView imageView = (ImageView) saveDialog.findViewById(R.id.show);   
  27.             // 獲取saveDialog的gesture_name組件   
  28.             final EditText gestureEditText = (EditText) saveDialog.findViewById(R.id.gesture_name);   
  29.            // 根據Gesture包含的手勢創建一個位圖   
  30.             Bitmap bitmap = gesture.toBitmap(12812810,0xffff0000);   
  31.             imageView.setImageBitmap(bitmap);   
  32.             // 使用對話框顯示saveDialog組件   
  33.             new AlertDialog.Builder(MainActivity.this).setView(saveDialog).setPositiveButton("保存"new OnClickListener() {   
  34.                 @Override   
  35.                 public void onClick(DialogInterface dialog,int which) {   
  36.                    // 獲取制定文件對應的手勢庫   
  37.                    GestureLibrary guestureLibrary = GestureLibraries.fromFile(Environment   
  38. .getExternalStorageDirectory().getPath()+ "/mygestures");   
  39.                   // 添加手勢   
  40.                   guestureLibrary.addGesture(gestureEditText.getText().toString(), gesture);   
  41.                   guestureLibrary.save();   
  42.                 }   
  43.            }).setNegativeButton("取消"null).show(); }   
  44.         });   
  45.     }   
  46. }   

 

五、識別用戶手勢 

  • recoginze(Gesture guesture)方法:識別手勢,該方法將會返回該手勢庫中所有與ges匹配的手勢兩個手勢的圖形越相似,相似度越高 

  • recogniza(Gusture ges)方法返回為ArrayList<Prediction>,啟動Prediction封裝了手勢的匹配信息,Predictin對象的name屬性代表了匹配的手勢名,score屬性代表了手勢的相似度; 

 

  • 應用實例(/chapter08/RecognizeGesture 

main_activity.xml文件  

  1. <?xml version="1.0" encoding="utf-8"?>   
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"   
  3.     android:layout_width="match_parent"   
  4.     android:layout_height="match_parent"   
  5.     android:orientation="vertical" >   
  6.     <android.gesture.GestureOverlayView   
  7.         android:id="@+id/gesture"   
  8.         android:layout_width="match_parent"   
  9.         android:layout_height="match_parent"   
  10.         android:gestureStrokeType="multiple" />   
  11. </LinearLayout>   
 

 

MainActivity.java文件 

 

  1. public class MainActivity extends Activity {   
  2.     // 定義手機編輯組件   
  3.     GestureOverlayView gestureOverlayView;   
  4.     // 記錄手機上已有的手勢庫   
  5.     GestureLibrary gestureLibrariLibrary;   
  6.    
  7.     @Override   
  8.     protected void onCreate(Bundle savedInstanceState) {   
  9.         super.onCreate(savedInstanceState);   
  10.         setContentView(R.layout.main_activity);   
  11.    
  12.         gestureOverlayView = (GestureOverlayView) findViewById(R.id.gesture);   
  13.         gestureLibrariLibrary = GestureLibraries.fromFile(Environment.getExternalStorageDirectory().getPath() + "/mygestures");   
  14.    
  15.         if (gestureLibrariLibrary.load()) {   
  16.             Toast.makeText(MainActivity.this"手勢文件裝在成功", Toast.LENGTH_LONG).show();   
  17.         } else {   
  18.             Toast.makeText(MainActivity.this"手勢文件裝在失敗", Toast.LENGTH_LONG).show();   
  19.         }   
  20.    
  21.         // 定義手勢編輯組件綁定監聽器   
  22.         gestureOverlayView.addOnGesturePerformedListener(new OnGesturePerformedListener() {   
  23.    
  24.         @Override   
  25.         public void onGesturePerformed(GestureOverlayView overlay,Gesture gesture) {   
  26.             // 識別用戶剛剛所繪制的手勢   
  27.             ArrayList<Prediction> predictions = gestureLibrariLibrary.recognize(gesture);   
  28.             ArrayList<String> result = new ArrayList<String>();   
  29.             // 遍歷所有找到的Prediction對象   
  30.             for (Prediction prediction : predictions) {   
  31.                 // 只有相似度大於0.2的手勢才會被輸出   
  32.                 if (prediction.score > 0.2) {   
  33.                     result.add("與手勢{" + prediction.name + "}相似度為:"+ prediction.score);   
  34.                 }   
  35.             }   
  36.    
  37.             if (result.size() > 0) {   
  38.                 ArrayAdapter<Object> arrayAdapter = new ArrayAdapter<Object>(MainActivity.this,   
  39. android.R.layout.simple_dropdown_item_1line,   
  40.                 result.toArray());   
  41.                 new AlertDialog.Builder(MainActivity.this).setAdapter(arrayAdapter, null).setPositiveButton("確定"null).show();   
  42.             } else {   
  43.                Toast.makeText(MainActivity.this"無法能找到匹配的手勢",   
  44.                Toast.LENGTH_LONG).show();   
  45.             }   
  46.         }});   
  47.     }   
  48. }  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM