zoukankan      html  css  js  c++  java
  • 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显示在抽屉中。
    效果图如下所示:

      

  • 相关阅读:
    YOLO2 (2) 测试自己的数据
    Ubuntu 14.04服务器配置 (1) 安装和配置
    window10+linux双系统安装
    机械纪元 尼奥
    如何标数据
    usb-cam (3)摄像机标定文件-ORB-SLAM标定文件
    ORB-SLAM2(3) ROS下实时跑ORB_SLAM2
    usb-cam(1)安装
    usb-cam (2)摄像机标定
    Linux下的压缩zip,解压缩unzip命令详解及实例
  • 原文地址:https://www.cnblogs.com/vus520/p/2700063.html
Copyright © 2011-2022 走看看