当前位置: 代码迷 >> Android >> Android 建立自个儿的手写笔画图案 Gesture Builder
  详细解决方案

Android 建立自个儿的手写笔画图案 Gesture Builder

热度:60   发布时间:2016-05-01 17:38:03.0
Android 建立自己的手写笔画图案 Gesture Builder

/****************************************************

大家都知道写博客会很累的,大热天的。

希望=转载请注明出处:http://blog.csdn.net/ta893115871

请不要可怜你的鼠标,(*^__^*) 嘻嘻……

***************************************************/

 

自SDK 1.6开始,Android手机已支持内置Gesture Builder程序,若是被Google签署(Signed)过出厂的手机应会内置此程序.

Gesture Builder提供了一手写识别的功能,让用户以类似于涂鸦的方式绘制一个手写符号,使之对应一个字符串名称,然而GestureBuilder功能虽完整,但在手写字符串的创建上却有些限制,如:制式化的建立方式、无法自行配置涂鸦区、查看手写(Gesture)以ListView来呈现等,在实际开发上稍显“复杂”了些。

下面看一下配置UI界面的activity_gesture_builder_demo.xml文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:background="@drawable/white" >    <LinearLayout        android:id="@+id/linear_top_id"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:layout_alignParentTop="true"       android:weightSum="2"        android:orientation="horizontal" >        <TextView            android:id="@+id/text_id"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:padding="@dimen/padding_medium"            android:text="@string/hello_world"            android:textSize="18sp"            tools:context=".GestureBuilderDemo" />        <EditText            android:id="@+id/edit_id"            android:layout_width="fill_parent"            android:layout_height="wrap_content"            android:inputType="text" />    </LinearLayout>    <android.gesture.GestureOverlayView        android:id="@+id/myGestures1"        android:layout_width="fill_parent"        android:layout_height="300dip"        android:layout_below="@+id/linear_top_id"        android:layout_marginRight="30sp"        android:gestureColor="#8909"        android:gestureStrokeType="multiple" /><!-- 	android:gestureStrokeType="multiple"   		  表示多笔支持,single则支持单一笔画 -->    <SlidingDrawer        android:id="@+id/slidingDreaer"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:content="@+id/content"        android:handle="@+id/handler"        android:orientation="horizontal" >        <ImageView            android:id="@+id/handler"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:contentDescription="@string/app_name"            android:src="@drawable/open" />        <ListView            android:id="@+id/content"            android:layout_width="fill_parent"            android:layout_height="wrap_content"            android:choiceMode="singleChoice"            android:background="@drawable/back"            android:divider="@drawable/divider" >        </ListView>    </SlidingDrawer>    <LinearLayout        android:id="@+id/linear_botton_id"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:weightSum="2"        style="@android:style/ButtonBar"         android:orientation="horizontal" >        <Button            android:id="@+id/button1_id"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_weight="1.0"            android:text="@string/str_button1" />        <Button            android:id="@+id/button2_id"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_weight="1.0"            android:text="@string/str_button2" />    </LinearLayout></RelativeLayout>

其中有一个TAG为<android.gesture. GestureOverlayView>的Widget,可称为“手写绘图区”,当中有两项较重要的属性,分别为android:layout_width设置为“fill_parent”以及android:gestureStrokeType设置为“multiple”,这表示为支持多笔画,若设置为“single”则仅支持单一笔画。

 

AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.gesturebuilderdemo"    android:versionCode="1"    android:versionName="1.0"  android:installLocation="preferExternal"    >    <uses-sdk        android:minSdkVersion="8"        android:targetSdkVersion="15" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>    <application        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <activity            android:name=".GestureBuilderDemo"            android:label="@string/title_activity_gesture_builder_demo" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application></manifest>


由于Gesture手写Libary文件"/sdcard/gestures"默认保存在SD存储卡中,所以需要写入External Storage的权限。

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

再看java文件中看几个函数:

Gesture对象是自GestureOverlayView.getGesture() 所取得的手写对象;GestureLibraries为保存手写背后所包含的意义(String),本范例利用GestureLibraries.fromFile()方法来加载预设的Gesture文件,倘若默认手机的SD存储卡中尚未创建Gesture手写数据文件,此程序也会处理创建新文件的工作。此外,程序中举例应用了GestureLibraries.addGesture()新建手写数据、GestureLibraries.save()保存写入手写数据GestureLibraries.load()加载手写数据、GestureLibraries. removeGesture()删除手写数据等方法。

GestureBuilderDemo.java

package com.example.gesturebuilderdemo;import java.io.File;import java.util.ArrayList;import java.util.List;import java.util.Set;import android.os.Bundle;import android.os.Environment;import android.app.Activity;import android.gesture.Gesture;import android.gesture.GestureLibraries;import android.gesture.GestureLibrary;import android.gesture.GestureOverlayView;import android.gesture.GestureOverlayView.OnGestureListener;import android.graphics.Bitmap;import android.graphics.Color;import android.util.Log;import android.view.KeyEvent;import android.view.Menu;import android.view.MotionEvent;import android.view.View;import android.view.View.OnClickListener;import android.view.View.OnKeyListener;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.ListView;import android.widget.SlidingDrawer;import android.widget.SlidingDrawer.OnDrawerCloseListener;import android.widget.SlidingDrawer.OnDrawerOpenListener;import android.widget.Toast;public class GestureBuilderDemo extends Activity {	private static final  String TAG="GestureBuilderDemo";		private Button mButton1, mButton2;	private GestureOverlayView mGestureOverlayView;//手写绘制区	private EditText mEditText;	private Gesture ges;	private GestureLibrary lib;	private String gesPath;	// ----------------------------	private ImageView mImageView;//拉动式抽屉	private SlidingDrawer mDrawer;//拉动式抽屉的手柄	private ListView mListView;//拉动式抽屉的内容	private List<String> gesNames = new ArrayList<String>();//保存手写的名称集合	private List<Bitmap> gesPics = new ArrayList<Bitmap>();//保存转换为手写的图片的集合		//------------------- -------	private LinearLayout layout_bottom;//底部的2个按钮布局	private LinearLayout layout_top;//顶部的2个按钮布局	private MyListAdapter adapter;//适配器		@Override	public void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		/* 查看SDCard是否存在 */		setContentView(R.layout.activity_gesture_builder_demo);		if (!Environment.MEDIA_MOUNTED.equals(Environment				.getExternalStorageState())) {			Toast.makeText(this, "SDCard不存在!", Toast.LENGTH_SHORT).show();			this.finish();		}		/* 取得系统默认的GestureLibrary的文件路径 */		gesPath = new File(Environment.getExternalStorageDirectory(),				"gestures").getAbsolutePath();		mButton1 = (Button) this.findViewById(R.id.button1_id);		mButton2 = (Button) this.findViewById(R.id.button2_id);		mGestureOverlayView = (GestureOverlayView) this				.findViewById(R.id.myGestures1);		mEditText = (EditText) this.findViewById(R.id.edit_id);		mButton1.setEnabled(false);		mImageView = (ImageView) this.findViewById(R.id.handler);		mDrawer = (SlidingDrawer) this.findViewById(R.id.slidingDreaer);		mListView = (ListView) this.findViewById(R.id.content);		mEditText.setOnKeyListener(keyListener);		mGestureOverlayView.addOnGestureListener(onGestureListener);		mButton1.setOnClickListener(listener1);		mButton2.setOnClickListener(listener2);		layout_bottom=(LinearLayout)this.findViewById(R.id.linear_botton_id);		layout_top=(LinearLayout)this.findViewById(R.id.linear_top_id);				adapter=new MyListAdapter(this,gesNames,gesPics);				getExitGesture();//读取SD卡中的/sdcard/gestures里建立的手写,并显示在ListView中		mListView.setAdapter(adapter);		mListView.setOnItemClickListener(list_listener);		mDrawer.setOnDrawerOpenListener(onDrawerOpenListener_open);		mDrawer.setOnDrawerCloseListener(onDrawerCloseListener_close);	}	OnItemClickListener  list_listener=new OnItemClickListener(){		public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,				long arg3) {			// TODO Auto-generated method stub			Toast.makeText(GestureBuilderDemo.this, "GestureName:"+gesNames.get(arg2),					Toast.LENGTH_SHORT).show();		}			};	//抽屉打开	OnDrawerOpenListener  onDrawerOpenListener_open=new OnDrawerOpenListener(){		public void onDrawerOpened() {			// TODO Auto-generated method stub			mImageView.setImageResource(R.drawable.close);			layout_bottom.setVisibility(View.GONE);			layout_top.setVisibility(View.GONE);			mGestureOverlayView.setVisibility(View.GONE);						getExitGesture();		}			};	//抽屉关闭	OnDrawerCloseListener  onDrawerCloseListener_close=new OnDrawerCloseListener(){		public void onDrawerClosed() {			// TODO Auto-generated method stub			mImageView.setImageResource(R.drawable.open);			layout_bottom.setVisibility(View.VISIBLE);			layout_top.setVisibility(View.VISIBLE);			mGestureOverlayView.setVisibility(View.VISIBLE);		}			};	//读取SD卡中的/sdcard/gestures里建立的手写,并显示在ListView中	public void getExitGesture() {		Log.i(TAG, "getExitGesture()");		gesNames.clear();		gesPics.clear();		File f = new File(gesPath);		lib = GestureLibraries.fromFile(f);		if (f.exists()) {			if (!lib.load()) {				Toast.makeText(GestureBuilderDemo.this, "加载失败!!",						Toast.LENGTH_SHORT).show();			} else {				Object[] obj = lib.getGestureEntries().toArray();				for (int i = 0; i < obj.length; i++) {					ArrayList<Gesture> al = lib.getGestures(obj[i].toString());				//	Log.i(TAG, "i="+i);					for (int j = 0; j < al.size(); j++) {				//		Log.i(TAG, "j="+j);				//		Log.i(TAG, "obj[i].toString()==="+obj[i].toString());						// 手写名称						gesNames.add(obj[i].toString());						Gesture gs = (Gesture) al.get(j);						//将手写转成Bitmap图片						gesPics.add(gs.toBitmap(50, 50, 12, Color.MAGENTA));					}				}			}		} else {			Toast.makeText(GestureBuilderDemo.this, "文件不存在!",					Toast.LENGTH_SHORT).show();		}				adapter.notifyDataSetChanged();	}	OnGestureListener onGestureListener = new OnGestureListener() {		public void onGesture(GestureOverlayView overlay, MotionEvent event) {			// TODO Auto-generated method stub		}		public void onGestureCancelled(GestureOverlayView overlay,				MotionEvent event) {			// TODO Auto-generated method stub		}		public void onGestureEnded(GestureOverlayView overlay, MotionEvent event) {			// TODO Auto-generated method stub			ges = overlay.getGesture();			if (ges != null					&& mEditText.getText().toString().trim().length() != 0) {				mButton1.setEnabled(true);			}		}		public void onGestureStarted(GestureOverlayView overlay,				MotionEvent event) {			// TODO Auto-generated method stub			ges = null;			mButton1.setEnabled(false);		}	};	OnKeyListener keyListener = new OnKeyListener() {		public boolean onKey(View arg0, int arg1, KeyEvent arg2) {			// TODO Auto-generated method stub			if (ges != null					&& mEditText.getText().toString().trim().length() != 0) {				mButton1.setEnabled(true);			} else {				mButton1.setEnabled(false);			}			return false;		}	};	@Override	public boolean onCreateOptionsMenu(Menu menu) {		getMenuInflater().inflate(R.menu.activity_gesture_builder_demo, menu);		return true;	}	OnClickListener listener1 = new OnClickListener() {		public void onClick(View arg0) {			// TODO Auto-generated method stub			String gestureName = mEditText.getText().toString().trim();			lib = GestureLibraries.fromFile(gesPath);			File f = new File(gesPath);			if (!f.exists()) {				/* 文件不存在就直接写入 */				lib.addGesture(gestureName, ges);				if (lib.save()) {					mEditText.setText("");					mGestureOverlayView.clear(true);					mButton1.setEnabled(false);					Toast.makeText(GestureBuilderDemo.this,							"保存成功,路径为:" + gesPath, Toast.LENGTH_SHORT).show();				} else {					Toast.makeText(GestureBuilderDemo.this, "保存失败!",							Toast.LENGTH_SHORT).show();				}			} else {				// 文件存在时,先读取已经存在的Gesture				if (lib.load()) {					/* 如果Library中存在相同名称,则先将其移除再写入 */					Set<String> set = lib.getGestureEntries();					if (set.contains(gestureName)) {						ArrayList<Gesture> list = lib.getGestures(gestureName);						for (int i = 0; i < list.size(); i++) {							//删除手写数据							lib.removeGesture(gestureName, list.get(i));						}					}					//新增手写数据					lib.addGesture(gestureName, ges);					// 保存写入手写数据					if (lib.save()) {						mEditText.setText("");						mGestureOverlayView.clear(true);						mButton1.setEnabled(false);						Toast.makeText(GestureBuilderDemo.this,								"保存成功,路径为:" + gesPath, Toast.LENGTH_SHORT)								.show();					} else {						Toast.makeText(GestureBuilderDemo.this, "保存失败!",								Toast.LENGTH_SHORT).show();					}				} else {					Toast.makeText(GestureBuilderDemo.this, "加载失败!",							Toast.LENGTH_SHORT).show();				}			}			mDrawer.toggle();		}	};	OnClickListener listener2 = new OnClickListener() {		public void onClick(View arg0) {			// TODO Auto-generated method stub			mEditText.setText("");			mGestureOverlayView.clear(true);			mButton1.setEnabled(false);		}	};}


ListView的适配器文件:

package com.example.gesturebuilderdemo;import java.util.List;import android.content.Context;import android.graphics.Bitmap;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;public class MyListAdapter extends BaseAdapter {	private Context mContext;	private List<String> gesNames ;	private List<Bitmap> gesPics ;		public MyListAdapter(Context mContext,List<String> gesNames,List<Bitmap> gesPics )	{		this.mContext=mContext;		this.gesNames=gesNames;		this.gesPics=gesPics;	}	public int getCount() {		// TODO Auto-generated method stub		return gesNames.size();	}	public Object getItem(int arg0) {		// TODO Auto-generated method stub		return gesNames.get(arg0);	}	public long getItemId(int position) {		// TODO Auto-generated method stub		return position;	}	public View getView(int position, View convertView, ViewGroup parent) {		// TODO Auto-generated method stub		convertView=	LayoutInflater.from(mContext).inflate(R.layout.list, null);		ImageView img=(ImageView)convertView.findViewById(R.id.img_id);		img.setImageBitmap(gesPics.get(position));				TextView text=(TextView)convertView.findViewById(R.id.text_id);		text.setText(gesNames.get(position));				return convertView;	}}


 

ListView的布局配置文件:

<?xml version="1.0" encoding="UTF-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent" >    <ImageView        android:id="@+id/img_id"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentLeft="true"        android:contentDescription="@string/app_name" />    <TextView        android:id="@+id/text_id"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_toRightOf="@+id/img_id"        android:lines="1"        android:textColor="#f699"        android:textSize="20sp"        android:textStyle="bold" /></RelativeLayout>


文件中有详细说明,不多说了。

当建立完手写和输入名称后自动把添加按钮Enable,所用的监听器为: mEditText.setOnKeyListener(keyListener);

点击添加按钮后悔自动打开抽屉获取以ListView显示在抽屉中。

界面如下所示:

 

 

 

 

  相关解决方案