2012092414530285

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=http://blog.csdn.net/ta893115871/article/details/"@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&lt;String&gt; gesNames = new ArrayList&lt;String&gt;();//保存手寫的名稱集合
private List&lt;Bitmap&gt; gesPics = new ArrayList&lt;Bitmap&gt;();//保存轉換为手寫的圖片的集合

//------------------- -------
private LinearLayout layout_bottom;//底部的2個<A class="relatedlink" target=_blank>按鈕</A><A class="relatedlink" target=_blank>布局</A>
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&lt;?&gt; 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 &lt; obj.length; i++) {
ArrayList&lt;Gesture&gt; al = lib.getGestures(obj[i].toString());
// Log.i(TAG, "i="+i);
for (int j = 0; j &lt; 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
&amp;&amp; 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
&amp;&amp; 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&lt;String&gt; set = lib.getGestureEntries();
if (set.contains(gestureName)) {
ArrayList&lt;Gesture&gt; list = lib.getGestures(gestureName);
for (int i = 0; i &lt; 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&lt;String&gt; gesNames ;
private List&lt;Bitmap&gt; gesPics ;

public MyListAdapter(Context mContext,List&lt;String&gt; gesNames,List&lt;Bitmap&gt; 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顯示在抽屜中。

arrow
arrow
    全站熱搜

    戮克 發表在 痞客邦 留言(0) 人氣()