Android的gesture的識別和自訂gesture

來源:互聯網
上載者:User

今天起介紹下和手勢和多點觸摸相關的知識。。。。。。

先上個一道菜,手勢的識別。。。。。

java.lang.Object   ↳android.view.View    ↳android.view.ViewGroup     ↳android.widget.FrameLayout      ↳android.gesture.GestureOverlayView

介紹下GestureOverlayView,這個透明的view就是讓你在上面畫手勢用的,可疊在其他View上面。

和這個類相關的還有三個介面,分別是

GestureOverlayView.OnGestureListener;

GestureOverlayView.OnGesturePerformedListener(作用:根據在GestureOverlayView上畫的手勢來識別是否匹配手勢庫裡的手勢);

GestureOverlayView.OnGesturingListener.

GestureOverlayView的xml的屬性介紹:

android:gestureStrokeType 

設定手勢的筆畫數,它有兩個值,GESTURE_STROKE_TYPE_MULTIPLE(多筆),GESTURE_STROKE_TYPE_SINGLE(一筆)

public final class GestureLibraries
 static GestureLibrary fromFile(File path)  static GestureLibrary fromFile(String path)  static GestureLibrary fromPrivateFile(Context context, String name)  static GestureLibrary fromRawResource(Context context, int resourceId)

想從SD卡或者raw的資源中直接載入手勢;

下面介紹下手勢的識別功能,先上代碼:

GestureIdentifyDemoActivity.xml

package com.potato;import java.util.ArrayList;import android.app.Activity;import android.gesture.Gesture;import android.gesture.GestureLibraries;import android.gesture.GestureLibrary;import android.gesture.GestureOverlayView;import android.gesture.Prediction;import android.os.Bundle;import android.widget.Toast;public class GestureIdentifyDemoActivity extends Activity {// 手勢庫GestureLibrary mGestureLib;/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);// 手勢畫板GestureOverlayView gestures = (GestureOverlayView) findViewById(R.id.gesture_overlay_view_test);// 手勢識別的監聽器gestures.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() {// 注1@Overridepublic void onGesturePerformed(GestureOverlayView overlay,Gesture gesture) {//從手勢庫中查詢匹配的內容,匹配的結果可能包括多個相似的結果,匹配度高的結果放在最前面  ArrayList<Prediction> predictions = mGestureLib.recognize(gesture);// 注3if (predictions.size() > 0) {Prediction prediction = (Prediction) predictions.get(0);// 匹配的手勢if (prediction.score > 1.0) {Toast.makeText(GestureIdentifyDemoActivity.this,prediction.name, Toast.LENGTH_SHORT).show();}}}});// 從raw中載入已經有的手勢庫mGestureLib = GestureLibraries.fromRawResource(this, R.raw.gestures);// 注2if (!mGestureLib.load()) {finish();}}}

注1:

gestures.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener()

手勢識別的監聽器。。。。

注2:

mGestureLib = GestureLibraries.fromRawResource(this, R.raw.gestures);

從res/raw/載入gestures手勢這個檔案

注3:

ArrayList<Prediction> predictions = mGestureLib.recognize(gesture);

從手勢庫中識別出和在GestureOverlayView所畫的手勢;

mian.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical" >    <TextView        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:text="輸入手勢:" />    <!-- 注意  android.gesture.要加,否則報錯,估計是找不到包-->    <android.gesture.GestureOverlayView        android:id="@+id/gesture_overlay_view_test"        android:layout_width="match_parent"        android:layout_height="0dip"        android:layout_weight="1.0"        android:gestureStrokeType="multiple" /></LinearLayout>

這裡要注意:android.gesture.GestureOverlayView這裡的不能用GestureOverlayView

下面介紹如何向手勢庫中增加自訂的手勢:

上代碼:

GestureBuilderDemoActivity.java

package com.potato;import java.io.File;import java.util.Collections;import java.util.Comparator;import java.util.HashMap;import java.util.Map;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.content.res.Resources;import android.gesture.Gesture;import android.gesture.GestureLibraries;import android.gesture.GestureLibrary;import android.graphics.Bitmap;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import android.os.Bundle;import android.os.Environment;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ArrayAdapter;import android.widget.Button;import android.widget.ListView;import android.widget.TextView;public class GestureBuilderDemoActivity extends Activity {private static final int STATUS_SUCCESS = 0;private static final int STATUS_CANCELLED = 1;private static final int STATUS_NO_STORAGE = 2;private static final int STATUS_NOT_LOADED = 3;private static final int REQUEST_NEW_GESTURE = 1;// 存放手勢的檔案private final File mStoreFile = new File(Environment.getExternalStorageDirectory(), "gestures");private GesturesAdapter mAdapter;private static GestureLibrary mGestureLib;private TextView mTvEmpty;Button mBtnAddGesture;Button mBtnIdentify;Resources mRes;ListView mListViewGesture;// 寬度、高度private int mThumbnailSize;// 密度private int mThumbnailInset;// 顏色private int mPathColor;static GestureLibrary getStore() {return mGestureLib;}/** * 手勢排序 */private final Comparator<NamedGesture> mSorter = new Comparator<NamedGesture>() {public int compare(NamedGesture object1, NamedGesture object2) {return object1.name.compareTo(object2.name);}};/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);mRes = getResources();mBtnAddGesture = (Button) findViewById(R.id.addButton);mBtnIdentify = (Button) findViewById(R.id.reloadButton);mPathColor = mRes.getColor(R.color.gesture_color);mThumbnailInset = (int) mRes.getDimension(R.dimen.gesture_thumbnail_inset);mThumbnailSize = (int) mRes.getDimension(R.dimen.gesture_thumbnail_size);mListViewGesture = (ListView) findViewById(android.R.id.list);mAdapter = new GesturesAdapter(this);mListViewGesture.setAdapter(mAdapter);if (mGestureLib == null) {mGestureLib = GestureLibraries.fromFile(mStoreFile);// 注1}mTvEmpty = (TextView) findViewById(android.R.id.empty);loadGestures();if (mListViewGesture.getAdapter().isEmpty()) {mListViewGesture.setEmptyView(mTvEmpty);mBtnAddGesture.setEnabled(false);} else {mBtnAddGesture.setEnabled(true);}}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (resultCode == RESULT_OK) {switch (requestCode) {case REQUEST_NEW_GESTURE:loadGestures();break;}}}/** * 識別手勢 */@SuppressWarnings({ "UnusedDeclaration" })public void identifyGestures(View v) {Intent intent = new Intent(this, GestureIdentifyDemoActivity.class);startActivity(intent);}/** * 建立手勢 * @param v */@SuppressWarnings({ "UnusedDeclaration" })public void addGesture(View v) {Intent intent = new Intent(this, CreateGestureActivity.class);startActivityForResult(intent, REQUEST_NEW_GESTURE);}/** * 載入手勢 * @return */private int loadGestures() {if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {return STATUS_NO_STORAGE;}final GestureLibrary gestureLib = mGestureLib;mAdapter.clear();if (gestureLib.load()) {// 注2for (String name : gestureLib.getGestureEntries()) {for (Gesture gesture : gestureLib.getGestures(name)) {final Bitmap bitmap = gesture.toBitmap(mThumbnailSize,// 注3mThumbnailSize, mThumbnailInset, mPathColor);final NamedGesture namedGesture = new NamedGesture();namedGesture.gesture = gesture;namedGesture.name = name;mAdapter.addBitmap(namedGesture.gesture.getID(), bitmap);mAdapter.add(namedGesture);}}mAdapter.sort(mSorter);// 注4mAdapter.notifyDataSetChanged();return STATUS_SUCCESS;}return STATUS_NOT_LOADED;}static class NamedGesture {String name;Gesture gesture;}private class GesturesAdapter extends ArrayAdapter<NamedGesture> {private final LayoutInflater mInflater;private final Map<Long, Drawable> mThumbnails = Collections.synchronizedMap(new HashMap<Long, Drawable>());public GesturesAdapter(Context context) {super(context, 0);mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);}void addBitmap(Long id, Bitmap bitmap) {mThumbnails.put(id, new BitmapDrawable(bitmap));}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {if (convertView == null) {convertView = mInflater.inflate(R.layout.list_item_gesture,parent, false);}final NamedGesture gesture = getItem(position);final TextView label = (TextView) convertView;label.setTag(gesture);label.setText(gesture.name);label.setCompoundDrawablesWithIntrinsicBounds(mThumbnails.get(gesture.gesture.getID()), null, null, null);return convertView;}};}

注1

mGestureLib = GestureLibraries.fromFile(mStoreFile);

從SD卡中載入已有的手勢;

注2

gestureLib.load()

從手勢庫載入手勢

注3

final Bitmap bitmap = gesture.toBitmap(mThumbnailSize,// 注3mThumbnailSize, mThumbnailInset, mPathColor);

把手勢轉換成bitmap

注4

排序

main.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:background="#009966"    android:orientation="vertical" >    <ListView        android:id="@android:id/list"        android:layout_width="fill_parent"        android:layout_height="0dip"        android:layout_weight="1.0" />    <LinearLayout        style="@android:style/ButtonBar"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal">        <Button            android:id="@+id/addButton"            android:layout_width="0dip"            android:layout_height="wrap_content"            android:layout_weight="1"            android:enabled="false"            android:onClick="addGesture"            android:text="button_add" />        <Button            android:id="@+id/reloadButton"            android:layout_width="0dip"            android:layout_height="wrap_content"            android:layout_weight="1"            android:onClick="identifyGestures"            android:text="button_identify" />    </LinearLayout></LinearLayout>

建立手勢

CreateGestureActivity.java

package com.potato;import android.app.Activity;import android.os.Bundle;import android.os.Environment;import android.view.View;import android.view.MotionEvent;import android.gesture.GestureOverlayView;import android.gesture.Gesture;import android.gesture.GestureLibrary;import android.widget.TextView;import android.widget.Toast;import java.io.File;public class CreateGestureActivity extends Activity {private static final float LENGTH_THRESHOLD = 120.0f;private Gesture mGesture;private View mDoneButton;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.create_gesture);mDoneButton = findViewById(R.id.done);GestureOverlayView overlay = (GestureOverlayView) findViewById(R.id.gestures_overlay);overlay.addOnGestureListener(new GesturesProcessor());}@Overrideprotected void onSaveInstanceState(Bundle outState) {super.onSaveInstanceState(outState);if (mGesture != null) {outState.putParcelable("gesture", mGesture);}}@Overrideprotected void onRestoreInstanceState(Bundle savedInstanceState) {super.onRestoreInstanceState(savedInstanceState);mGesture = savedInstanceState.getParcelable("gesture");if (mGesture != null) {final GestureOverlayView overlay = (GestureOverlayView) findViewById(R.id.gestures_overlay);overlay.post(new Runnable() {public void run() {overlay.setGesture(mGesture);}});mDoneButton.setEnabled(true);}}/** * 增加手勢的按鈕 * @param v */public void addGesture(View v) {if (mGesture != null) {final TextView input = (TextView) findViewById(R.id.gesture_name);final CharSequence name = input.getText();if (name.length() == 0) {input.setError("輸入gesture的名字!");return;}// 把手勢增加到手勢庫final GestureLibrary store = GestureBuilderDemoActivity.getStore();// 注1store.addGesture(name.toString(), mGesture);store.save();setResult(RESULT_OK);final String path = new File(Environment.getExternalStorageDirectory(), "gestures").getAbsolutePath();Toast.makeText(this, "儲存成功" + path, Toast.LENGTH_LONG).show();} else {setResult(RESULT_CANCELED);}finish();}/** * 取消手勢 * @param v */public void cancelGesture(View v) {setResult(RESULT_CANCELED);finish();}/** * 手勢監聽著 * @author Administrator * */private class GesturesProcessor implementsGestureOverlayView.OnGestureListener {public void onGestureStarted(GestureOverlayView overlay,MotionEvent event) {mDoneButton.setEnabled(false);mGesture = null;}public void onGesture(GestureOverlayView overlay, MotionEvent event) {}public void onGestureEnded(GestureOverlayView overlay, MotionEvent event) {// 擷取在GestureOverlayView手勢mGesture = overlay.getGesture();// 注2if (mGesture.getLength() < LENGTH_THRESHOLD) {overlay.clear(false);}mDoneButton.setEnabled(true);}public void onGestureCancelled(GestureOverlayView overlay,MotionEvent event) {}}}

注1

final GestureLibrary store = GestureBuilderDemoActivity.getStore();// 注1store.addGesture(name.toString(), mGesture);store.save();

手勢增加到手勢庫

注2

擷取在GestureOverlayView手勢

create_gesture.xml\

<?xml version="1.0" encoding="utf-8"?><LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"        android:orientation="vertical">    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal">            <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginRight="6dip"            android:text="prompt_gesture_name"            android:textAppearance="?android:attr/textAppearanceMedium" />                <EditText            android:id="@+id/gesture_name"            android:layout_width="0dip"            android:layout_weight="1.0"            android:layout_height="wrap_content"            android:maxLength="40"            android:singleLine="true" />    </LinearLayout>        <android.gesture.GestureOverlayView        android:id="@+id/gestures_overlay"        android:layout_width="match_parent"        android:layout_height="0dip"        android:layout_weight="1.0"        android:gestureStrokeType="multiple" />    <LinearLayout        style="@android:style/ButtonBar"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal">        <Button            android:id="@+id/done"            android:layout_width="0dip"            android:layout_height="wrap_content"            android:layout_weight="1"            android:enabled="false"            android:onClick="addGesture"            android:text="button_done" />            <Button            android:layout_width="0dip"            android:layout_height="wrap_content"            android:layout_weight="1"            android:onClick="cancelGesture"            android:text="button_discard" />        </LinearLayout>    </LinearLayout>

注意,不要忘記,寫入手勢時,一定要增加許可權,寫入sd卡

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

有問題,請留言或者發郵件

ligexiao@gmail.com

原始碼:http://download.csdn.net/detail/alex0203/3868687

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.