`

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

阅读更多

转自:http://www.cnblogs.com/vus520/archive/2012/09/24/2700063.html

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开发工具集的一部分,用于帮助开发者创建和管理自定义的手势识别。在Android应用中,手势识别可以提升用户体验,让用户通过简单的滑动、点击等动作来执行特定的操作。...

    GestureBuilder

    【GestureBuilder】是一款专为Android平台设计的手势创建工具,它允许用户自定义手势操作,并将其保存至SDCard(外部存储卡)的特定目录中,以便在应用中使用。通过这款工具,开发者或用户可以轻松地扩展应用程序的...

    android GestureBuilder源代码

    GestureBuilder是Android SDK中用于构建和编辑手势库的一个工具,它允许开发者创建自定义的手势并将其应用于应用程序中,以实现更直观、更人性化的用户交互。本文将深入探讨GestureBuilder的源代码,分析其工作原理...

    gesturebuilder

    在Android平台上,手势Builder(GestureBuilder)是一种工具,它允许开发者创建和管理自定义的手势。这个工具可以用来构建手势库,这些库包含了各种手势,然后可以在应用程序中使用,以实现用户与应用的互动。通过...

    GestureBuilder手势构造器

    GestureBuilder手势构造器是一款强大的工具,它允许开发者和用户预先定义并存储一系列定制的手势,以便在各种应用程序或交互场景中使用。这个工具的核心功能在于它的灵活性和可扩展性,使得用户可以根据自己的需求...

    手势电话 gesturebuilder

    这是在android gesturebuilder基础上开发的一个小小创意,通过将一个手势和电话簿中的联系人关联 打电话发短信不用翻电话簿 直接一个手势 就搞定 这个程序在删除手势后可能会引起关联错误 有兴趣的朋友可以在源码上...

    gesturebuilder.zip

    GestureBuilder是Android SDK提供的一种工具,用于创建和编辑自定义的手势库,使得开发者能够轻松地集成手势识别功能到自己的应用程序中。本文将深入探讨GestureBuilder的使用方法、工作原理以及相关知识点。 一、...

    安卓开发-GestureBuilder.zip

    1. 启动GestureBuilder应用:首先,你需要在Android Studio中找到GestureBuilder应用或库,并启动它。这通常位于Android SDK的tools目录下。 2. 录制手势:在空白画布上,使用鼠标或触控板模拟用户在设备屏幕上进行...

    创建一个名为RICK的手写符号

    通过使用GestureBuilder,开发者可以轻松地创建并保存各种手写笔画模式,以供日后使用。 #### GestureBuilder介绍 GestureBuilder是Google为Android开发者提供的一个用于创建和编辑手势的工具。它允许开发者绘制...

    Android代码-android-gesture-detectors

    Android Gesture Detectors Framework Introduction Since I was amazed Android has a ScaleGestureDetector since API level 8 but (still) no such thing as a RotateGestureDetector I decided to create this ...

    Android Gesture手势源码

    在Android开发中,手势识别是增强用户交互体验的重要技术之一。`Android Gesture`是指通过...在`HelloGesture`项目中,我们可以深入研究源码,了解其如何实现特定数字的手势识别,进一步提升自己的Android开发技能。

    Android手势gesture和ImageView综合测试

    - **Gesture Builder**: 开发者可以使用Gesture Builder工具创建手势库,该库包含一系列手势模板,用于匹配用户在屏幕上绘制的动作。 - **Gesture Library**: 存储手势模板的数据库,GestureOverlayView可以与之...

    android手写上传

    在Android平台上,手写上传是一项常见的功能,尤其在教育、笔记、签名等应用场景中非常实用。这个资源包可能包含了一个实现这一功能的示例代码或库,方便开发者集成到自己的应用中。以下是对这一主题的详细说明: 1...

    Android代码-访米聊手写和涂鸦源码.zip

    在Android平台上,开发一款具有手写和涂鸦功能的应用是一项挑战性的任务,因为这涉及到复杂的图形处理和用户交互。米聊作为一款知名的即时通讯应用,其手写和涂鸦功能无疑为用户提供了丰富的交流方式。这份"访米聊...

    Gesture手势添加与识别

    Gesture gesture = new Gesture.Builder().addStroke(new Gesture.Stroke(path)).build(); gestureStore.addGesture("MyGesture", gesture); gestureStore.save(new File("/sdcard/gestures.gest")); ``` 2. 手势...

    Android应用源码Gestures源码.zip

    用户可以在屏幕上画出手势,GestureBuilder会记录这一过程并生成对应的Gesture对象。 7. **GestureOverlayView**:这是一个自定义视图,可以叠加在其他UI元素上,用户可以直接在上面绘制手势。它提供了识别手势的...

    Android API 16 手势生成项目

    5. **自定义手势库**:开发者可以创建自己的手势库,包含多种预定义的手势,例如滑动、点击、双击、长按等,用户也可以通过GestureBuilder添加新的手势到库中。 6. **手势识别阈值**:为了提高识别的准确性,开发者...

    androidGesture_android_

    本文将深入探讨Android手势识别技术,并结合给定的“androidGesture_android_”项目实例,来阐述如何在Android应用中实现手势识别功能。 首先,Android的手势识别主要依赖于` GestureDetector`类,它是Android SDK...

    android手势识别讲解源码

    6. **自定义手势**:开发者可以通过GestureBuilder创建自己的手势库,每个手势都有一个唯一的ID和对应的名称。这样,当用户在屏幕上绘制出已定义的手势时,应用程序就可以根据ID执行相应的功能,比如打开特定的活动...

    安卓Android源码——gesture-imageview.zip

    Android SDK提供了一个叫做`android.gesture`的库,它包含了`GestureOverlayView`和`Gesture`类,用于识别和处理手势。然而,这个项目可能使用了第三方库,如`android.view.ScaleGestureDetector`和`android.view....

Global site tag (gtag.js) - Google Analytics