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

利用反射去存储对对象到SharedPreferences
http://www.eoeandroid.com/thread-202940-1-1.html

基于Android平台的车辆信息查询系统的开发
http://www.eoeandroid.com/thread-202933-1-1.html

【每日话题】程序猿早餐都吃啥?是吃还是不吃呢?
http://www.eoeandroid.com/thread-202803-1-1.html

 

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显示在抽屉中。
效果图如下所示:

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

 

 

 

你可能感兴趣的:(android)