Android 建立自己的手寫筆畫圖案 Gesture Builder

來源:互聯網
上載者:User

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

大家都知道寫部落格會很累的,大熱天的。

希望=轉載請註明出處: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;//適配器@Overridepublic 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 stubToast.makeText(GestureBuilderDemo.this, "GestureName:"+gesNames.get(arg2),Toast.LENGTH_SHORT).show();}};//抽屜開啟OnDrawerOpenListener  onDrawerOpenListener_open=new OnDrawerOpenListener(){public void onDrawerOpened() {// TODO Auto-generated method stubmImageView.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 stubmImageView.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 stubges = 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 stubges = null;mButton1.setEnabled(false);}};OnKeyListener keyListener = new OnKeyListener() {public boolean onKey(View arg0, int arg1, KeyEvent arg2) {// TODO Auto-generated method stubif (ges != null&& mEditText.getText().toString().trim().length() != 0) {mButton1.setEnabled(true);} else {mButton1.setEnabled(false);}return false;}};@Overridepublic 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 stubString 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 {// 檔案存在時,先讀取已經存在的Gestureif (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 stubmEditText.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 stubreturn gesNames.size();}public Object getItem(int arg0) {// TODO Auto-generated method stubreturn gesNames.get(arg0);}public long getItemId(int position) {// TODO Auto-generated method stubreturn position;}public View getView(int position, View convertView, ViewGroup parent) {// TODO Auto-generated method stubconvertView=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顯示在抽屜中。

介面如下所示:

 

 

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.