android第二十天——手势识别

创建手势库及应用

/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package cn.class3g.activity;

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;

@Override
protected 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());
}

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);

if (mGesture != null) {
outState.putParcelable("gesture", mGesture);
}
}

@Override
protected 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);
}
}

@SuppressWarnings({"UnusedDeclaration"})
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(getString(R.string.error_missing_name));
return;
}

final GestureLibrary store = GestureBuilderActivity.getStore();
store.addGesture(name.toString(), mGesture);
store.save();

setResult(RESULT_OK);

final String path = new File(Environment.getExternalStorageDirectory(),
"gestures").getAbsolutePath();
Toast.makeText(this, getString(R.string.save_success, path), Toast.LENGTH_LONG).show();
} else {
setResult(RESULT_CANCELED);
}

finish();

}

@SuppressWarnings({"UnusedDeclaration"})
public void cancelGesture(View v) {
setResult(RESULT_CANCELED);
finish();
}

private class GesturesProcessor implements GestureOverlayView.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) {
mGesture = overlay.getGesture();
if (mGesture.getLength() < LENGTH_THRESHOLD) {
overlay.clear(false);
}
mDoneButton.setEnabled(true);
}

public void onGestureCancelled(GestureOverlayView overlay, MotionEvent event) {
}
}
}

/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package cn.class3g.activity;

import android.app.Dialog;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.os.Bundle;
import android.os.AsyncTask;
import android.os.Environment;
import android.view.View;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.gesture.GestureLibrary;
import android.gesture.Gesture;
import android.gesture.GestureLibraries;
import android.widget.TextView;
import android.widget.EditText;
import android.widget.AdapterView;
import android.widget.Toast;
import android.widget.ArrayAdapter;
import android.content.DialogInterface;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.text.TextUtils;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.BitmapDrawable;

import java.util.Map;
import java.util.Collections;
import java.util.HashMap;
import java.util.Comparator;
import java.util.Set;
import java.io.File;

public class GestureBuilderActivity extends ListActivity {
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 MENU_ID_RENAME = 1;
private static final int MENU_ID_REMOVE = 2;

private static final int DIALOG_RENAME_GESTURE = 1;

private static final int REQUEST_NEW_GESTURE = 1;

// Type: long (id)
private static final String GESTURES_INFO_ID = "gestures.info_id";

private final File mStoreFile = new File(Environment.getExternalStorageDirectory(), "gestures");

private final Comparator<NamedGesture> mSorter = new Comparator<NamedGesture>() {
public int compare(NamedGesture object1, NamedGesture object2) {
return object1.name.compareTo(object2.name);
}
};

private static GestureLibrary sStore;

private GesturesAdapter mAdapter;
private GesturesLoadTask mTask;
private TextView mEmpty;

private Dialog mRenameDialog;
private EditText mInput;
private NamedGesture mCurrentRenameGesture;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.gestures_list);

mAdapter = new GesturesAdapter(this);
setListAdapter(mAdapter);

if (sStore == null) {
sStore = GestureLibraries.fromFile(mStoreFile);
}
mEmpty = (TextView) findViewById(android.R.id.empty);
loadGestures();

registerForContextMenu(getListView());
}

static GestureLibrary getStore() {
return sStore;
}

@SuppressWarnings({"UnusedDeclaration"})
public void reloadGestures(View v) {
loadGestures();
}

@SuppressWarnings({"UnusedDeclaration"})
public void addGesture(View v) {
Intent intent = new Intent(this, CreateGestureActivity.class);
startActivityForResult(intent, REQUEST_NEW_GESTURE);
}

@Override
protected 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;
}
}
}

private void loadGestures() {
if (mTask != null && mTask.getStatus() != GesturesLoadTask.Status.FINISHED) {
mTask.cancel(true);
}
mTask = (GesturesLoadTask) new GesturesLoadTask().execute();
}

@Override
protected void onDestroy() {
super.onDestroy();

if (mTask != null && mTask.getStatus() != GesturesLoadTask.Status.FINISHED) {
mTask.cancel(true);
mTask = null;
}

cleanupRenameDialog();
}

private void checkForEmpty() {
if (mAdapter.getCount() == 0) {
mEmpty.setText(R.string.gestures_empty);
}
}

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);

if (mCurrentRenameGesture != null) {
outState.putLong(GESTURES_INFO_ID, mCurrentRenameGesture.gesture.getID());
}
}

@Override
protected void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);

long id = state.getLong(GESTURES_INFO_ID, -1);
if (id != -1) {
final Set<String> entries = sStore.getGestureEntries();
out: for (String name : entries) {
for (Gesture gesture : sStore.getGestures(name)) {
if (gesture.getID() == id) {
mCurrentRenameGesture = new NamedGesture();
mCurrentRenameGesture.name = name;
mCurrentRenameGesture.gesture = gesture;
break out;
}
}
}
}
}

@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenu.ContextMenuInfo menuInfo) {

super.onCreateContextMenu(menu, v, menuInfo);

AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
menu.setHeaderTitle(((TextView) info.targetView).getText());

menu.add(0, MENU_ID_RENAME, 0, R.string.gestures_rename);
menu.add(0, MENU_ID_REMOVE, 0, R.string.gestures_delete);
}

@Override
public boolean onContextItemSelected(MenuItem item) {
final AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo)
item.getMenuInfo();
final NamedGesture gesture = (NamedGesture) menuInfo.targetView.getTag();

switch (item.getItemId()) {
case MENU_ID_RENAME:
renameGesture(gesture);
return true;
case MENU_ID_REMOVE:
deleteGesture(gesture);
return true;
}

return super.onContextItemSelected(item);
}

private void renameGesture(NamedGesture gesture) {
mCurrentRenameGesture = gesture;
showDialog(DIALOG_RENAME_GESTURE);
}

@Override
protected Dialog onCreateDialog(int id) {
if (id == DIALOG_RENAME_GESTURE) {
return createRenameDialog();
}
return super.onCreateDialog(id);
}

@Override
protected void onPrepareDialog(int id, Dialog dialog) {
super.onPrepareDialog(id, dialog);
if (id == DIALOG_RENAME_GESTURE) {
mInput.setText(mCurrentRenameGesture.name);
}
}

private Dialog createRenameDialog() {
final View layout = View.inflate(this, R.layout.dialog_rename, null);
mInput = (EditText) layout.findViewById(R.id.name);
((TextView) layout.findViewById(R.id.label)).setText(R.string.gestures_rename_label);

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setIcon(0);
builder.setTitle(getString(R.string.gestures_rename_title));
builder.setCancelable(true);
builder.setOnCancelListener(new Dialog.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
cleanupRenameDialog();
}
});
builder.setNegativeButton(getString(R.string.cancel_action),
new Dialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
cleanupRenameDialog();
}
}
);
builder.setPositiveButton(getString(R.string.rename_action),
new Dialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
changeGestureName();
}
}
);
builder.setView(layout);
return builder.create();
}

private void changeGestureName() {
final String name = mInput.getText().toString();
if (!TextUtils.isEmpty(name)) {
final NamedGesture renameGesture = mCurrentRenameGesture;
final GesturesAdapter adapter = mAdapter;
final int count = adapter.getCount();

// Simple linear search, there should not be enough items to warrant
// a more sophisticated search
for (int i = 0; i < count; i++) {
final NamedGesture gesture = adapter.getItem(i);
if (gesture.gesture.getID() == renameGesture.gesture.getID()) {
sStore.removeGesture(gesture.name, gesture.gesture);
gesture.name = mInput.getText().toString();
sStore.addGesture(gesture.name, gesture.gesture);
break;
}
}

adapter.notifyDataSetChanged();
}
mCurrentRenameGesture = null;
}

private void cleanupRenameDialog() {
if (mRenameDialog != null) {
mRenameDialog.dismiss();
mRenameDialog = null;
}
mCurrentRenameGesture = null;
}

private void deleteGesture(NamedGesture gesture) {
sStore.removeGesture(gesture.name, gesture.gesture);
sStore.save();

final GesturesAdapter adapter = mAdapter;
adapter.setNotifyOnChange(false);
adapter.remove(gesture);
adapter.sort(mSorter);
checkForEmpty();
adapter.notifyDataSetChanged();

Toast.makeText(this, R.string.gestures_delete_success, Toast.LENGTH_SHORT).show();
}

private class GesturesLoadTask extends AsyncTask<Void, NamedGesture, Integer> {
private int mThumbnailSize;
private int mThumbnailInset;
private int mPathColor;

@Override
protected void onPreExecute() {
super.onPreExecute();

final Resources resources = getResources();
mPathColor = resources.getColor(R.color.gesture_color);
mThumbnailInset = (int) resources.getDimension(R.dimen.gesture_thumbnail_inset);
mThumbnailSize = (int) resources.getDimension(R.dimen.gesture_thumbnail_size);

findViewById(R.id.addButton).setEnabled(false);
findViewById(R.id.reloadButton).setEnabled(false);

mAdapter.setNotifyOnChange(false);
mAdapter.clear();
}

@Override
protected Integer doInBackground(Void... params) {
if (isCancelled()) return STATUS_CANCELLED;
if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
return STATUS_NO_STORAGE;
}

final GestureLibrary store = sStore;

if (store.load()) {
for (String name : store.getGestureEntries()) {
if (isCancelled()) break;

for (Gesture gesture : store.getGestures(name)) {
final Bitmap bitmap = gesture.toBitmap(mThumbnailSize, mThumbnailSize,
mThumbnailInset, mPathColor);
final NamedGesture namedGesture = new NamedGesture();
namedGesture.gesture = gesture;
namedGesture.name = name;

mAdapter.addBitmap(namedGesture.gesture.getID(), bitmap);
publishProgress(namedGesture);
}
}

return STATUS_SUCCESS;
}

return STATUS_NOT_LOADED;
}

@Override
protected void onProgressUpdate(NamedGesture... values) {
super.onProgressUpdate(values);

final GesturesAdapter adapter = mAdapter;
adapter.setNotifyOnChange(false);

for (NamedGesture gesture : values) {
adapter.add(gesture);
}

adapter.sort(mSorter);
adapter.notifyDataSetChanged();
}

@Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);

if (result == STATUS_NO_STORAGE) {
getListView().setVisibility(View.GONE);
mEmpty.setVisibility(View.VISIBLE);
mEmpty.setText(getString(R.string.gestures_error_loading,
mStoreFile.getAbsolutePath()));
} else {
findViewById(R.id.addButton).setEnabled(true);
findViewById(R.id.reloadButton).setEnabled(true);
checkForEmpty();
}
}
}

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));
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.gestures_item, 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;
}
}
}

package cn.class3g.activity;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Intent;
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.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class Gesture_testActivity extends Activity {

GestureLibrary gLibrary;
GestureOverlayView gestureView;
boolean loatState =false;
Button button=null;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

init();


}
private void init() {

button= (Button) this.findViewById(R.id.button);

button.setOnClickListener(new View.OnClickListener() {


public void onClick(View v) {

Intent intent =new Intent();

intent.setClass(Gesture_testActivity.this, GestureBuilderActivity.class);

startActivity(intent);

}
});



gestureView =(GestureOverlayView) this.findViewById(R.id.myGestureView);

gestureView.addOnGesturePerformedListener(new myOnGesturePerformedListener());


//创建手势库对象 GestureLibrary
gLibrary = GestureLibraries.fromRawResource(this, R.raw.gestures);

//加载手势库资源

loatState= gLibrary.load();
}

private final class myOnGesturePerformedListener implements OnGesturePerformedListener{


public void onGesturePerformed(GestureOverlayView overlay,
Gesture gesture) {

if(loatState){

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

if(!predictions.isEmpty()){

Prediction prediction =predictions.get(0);

if(prediction.score>5){

if("close".equals(prediction.name)){

finish();
}else if("call".equals(prediction.name)){

Intent intent =new Intent(Intent.ACTION_CALL,Uri.parse("tel:13312345678"));

startActivity(intent);
}else{

showToast(R.string.notrecognize);
}
}

}else{

showToast(R.string.noprediction);
}

}


}


}

private void showToast(int resId) {

Toast.makeText(this, resId ,Toast.LENGTH_LONG).show();

}



}

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.class3g.activity"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="android.permission.CALL_PHONE"/>

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:label="@string/app_name"
android:name=".Gesture_testActivity" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<activity
android:name=".CreateGestureActivity"
android:label="@string/label_create_gesture" />

<activity
android:name=".GestureBuilderActivity"
android:label="@string/label_create_gesture" />
</application>

</manifest>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值