建立自己的手写笔画图案

来源:互联网 发布:windows所有快捷键 编辑:程序博客网 时间:2024/06/09 15:35
 建立自己的手写笔画图案

范例说明

自SDK 1.6开始,Android手机已支持内置Gesture Builder程序,若是被Google签署(Signed)过出厂的手机应会内置此程序,如果是程序开发人员,可在SDK文件夹里的“\android\platforms\ android\samples\GestureBuilder”找到这支程序的源代码,编译后即可生成各SDK版本可使用的Gesture Builder程序(apk)自行安装使用。

Gesture Builder提供了一手写识别的功能,让用户以类似于涂鸦的方式绘制一个手写符号,使之对应一个字符串名称,然而GestureBuilder功能虽完整,但在手写字符串的创建上却有些限制,如:制式化的建立方式、无法自行配置涂鸦区、查看手写(Gesture)以ListView来呈现等,在实际开发上稍显“复杂”了些。

本范例程序练习,是编写一个迷你版的Gesture Builder,可以通过全屏(GestureOverlayView)接收User的手写,并让我们“共享”系统预设使用的Gesture Library,在日后的项目开发中,便可依据此范例作为开发模板,创建、保存手写笔画图案。

<!--[endif]-->

▲ 图5-28  创建一个名为RICK的手写符号

范例程序

res/layout/main.xml

我们可以看到在res/layout/main.xml版面配置中,其中有一个TAG为<android.gesture. GestureOverlayView>的Widget,可称为“手写绘图区”,当中有两项较重要的属性,分别为android:layout_width设置为“fill_parent”以及android:gestureStrokeType设置为“multiple”,这表示为支持多笔画,若设置为“single”则仅支持单一笔画。

 

<android.gesture.GestureOverlayView

  android:id="@+id/myGestures1"

  android:layout_width="fill_parent"

  android:layout_height="0dip"

  android:layout_weight="1.0"

  android:gestureStrokeType="multiple"

/>

src/irdc.ex05_25/EX05_25.java

Gesture对象是自GestureOverlayView.getGesture() 所取得的手写对象;GestureLibraries为保存手写背后所包含的意义(String),本范例利用GestureLibraries.fromFile()方法来加载预设的Gesture文件,倘若默认手机的SD存储卡中尚未创建Gesture手写数据文件,此程序也会处理创建新文件的工作。此外,程序中举例应用了GestureLibraries.addGesture()新建手写数据、GestureLibraries.save()保存写入手写数据GestureLibraries.load()加载手写数据、GestureLibraries. removeGesture()删除手写数据等方法。

 

/* import程序略 */

import android.gesture.Gesture;

import android.gesture.GestureLibraries;

import android.gesture.GestureLibrary;

import android.gesture.GestureOverlayView;

import android.view.MotionEvent;

 

public class EX05_25 extends Activity

{

  private Gesture ges;

  private GestureLibrary lib;

  private GestureOverlayView overlay;

  private Button button01,button02;

  private EditText et;

  private String gesPath;

 

  /** Called when the activity is first created. */

  @Override

  public void onCreate(Bundle savedInstanceState)

  {

    super.onCreate(savedInstanceState);

    /* 加载main.xml Layout */

    setContentView(R.layout.main);

    

    /* 查看SDCard是否存在 */

    if(!Environment.MEDIA_MOUNTED.equals

        (Environment.getExternalStorageState()))

    {

      /* SD卡不存在,显示Toast信息 */

      Toast.makeText(EX05_25.this,"SD卡不存在!程序无法执行",

                     Toast.LENGTH_LONG).show();

      finish();

    }

    /* 以findViewById()取得对象 */

    et = (EditText)this.findViewById(R.id.myEditText1);

    button01 = (Button)this.findViewById(R.id.myButton1);

    button02 = (Button)this.findViewById(R.id.myButton2);

    overlay = (GestureOverlayView) findViewById(R.id.myGestures1);

 

    /* 取得系统默认的GestureLibrary文件路径 */

    gesPath = new File

    (

      Environment.getExternalStorageDirectory(),"gestures"

    ).getAbsolutePath();

 

    /* 设置EditText的OnKeyListener */

    et.setOnKeyListener(new EditText.OnKeyListener()

    {

      @Override

      public boolean onKey(View v, int keyCode, KeyEvent event)

      {

        /* 名称与手写都均设置好时将新建的Button enable */

        if(ges!=null&&et.getText().length()!=0)

        {

          button01.setEnabled(true);

        }

        else

        {

          button01.setEnabled(false);

        }

        return false;

      }

    });

   

    /* 设置Overlay的OnGestureListener */

    overlay.addOnGestureListener

    (new GestureOverlayView.OnGestureListener()

    {

      @Override

      public void onGesture

      (GestureOverlayView overlay,MotionEvent event)

      {

      }

      /* 开始画手写时将添加的Button disable,并清除Gesture */

      @Override

      public void onGestureStarted

      (GestureOverlayView overlay,MotionEvent event)

      {

        button01.setEnabled(false);

        ges = null;

      }

      /* 手写画完时判断名称与手写是否完整建立 */

      @Override

      public void onGestureEnded

      (GestureOverlayView overlay, MotionEvent event)

      {

        ges = overlay.getGesture();

        if (ges!=null&&et.getText().length()!=0)

        {

          button01.setEnabled(true);

        }

      }

      @Override

      public void onGestureCancelled

      (GestureOverlayView overlay, MotionEvent event)

      {

      }

    });

   

    /* 设定button01的OnClickListener */

    button01.setOnClickListener(new Button.OnClickListener()

    {

      @Override

      public void onClick(View v)

      {

        String gesName=et.getText().toString();

        try

        {

          File file = new File(gesPath);

          lib = GestureLibraries.fromFile(gesPath);

         

          if(!file.exists())

          {

            /* 文件不存在就直接写入 */

            lib.addGesture(gesName,ges);

            if(lib.save())

            {

              /* 将设置画面数据清除 */

              et.setText("");

              button01.setEnabled(false);

              overlay.clear(true);

              /* 保存成功,显示Toast信息 */

              Toast.makeText

              (

                EX05_25.this,getString(R.string.save_success)+":"+

                gesPath,Toast.LENGTH_LONG

              ).show();

            }

            else

            {

              /* 保存失败,显示Toast信息 */

              Toast.makeText

              (

                EX05_25.this, getString(R.string.save_failed)+":"+

                gesPath,Toast.LENGTH_LONG

              ).show();

            }

          }

          else

          {

            /* 文件存在时先读取已保存的Gesture */

            if (!lib.load())

            {

              /* Library读取失败,显示Toast信息 */

              Toast.makeText

              (

                EX05_25.this, getString(R.string.load_failed)+":"+

                gesPath,Toast.LENGTH_LONG

              ).show();

            }

            else

            {

              /* 如果Library中存在相同名称,则先将其移除再写入 */

              Set<String> en=lib.getGestureEntries();

              if(en.contains(gesName))

              {

                ArrayList<Gesture> al=lib.getGestures(gesName);

                for(int i=0;i<al.size();i++)

                {

                  lib.removeGesture(gesName,al.get(i));

                }

              }

              lib.addGesture(gesName,ges);

              if(lib.save())

              {

                /* 将设置画面数据清除 */

                et.setText("");

                button01.setEnabled(false);

                overlay.clear(true);

                /* 保存成功,显示Toast信息 */

                Toast.makeText

                (

                  EX05_25.this,getString(R.string.save_success)+":"+

                  gesPath,Toast.LENGTH_LONG

                ).show();

              }

              else

              { 

                /* 保存失败,显示Toast信息 */

                Toast.makeText

                (

                  EX05_25.this, getString(R.string.save_failed)+":"+

                  gesPath,Toast.LENGTH_LONG

                ).show();

              }

            }

          }

        }

        catch(Exception e)

        {

          e.printStackTrace();

        }

      }

    });

   

    /* 设置button02的OnClickListener,清除建立的Overlay */

    button02.setOnClickListener(new Button.OnClickListener()

    {

      @Override

      public void onClick(View v)

      {

        et.setText("");

        button01.setEnabled(false);

        overlay.clear(true);

      }

    });

  }

}

AndroidManifest.xml

由于Gesture手写Library文件“/sdcard/gestures”默认保存在SD存储卡中,故需要写入External Storage的相关权限。

 

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

 

扩展学习

如果要加载Gesture手写的Library文件,主程序中所使用的方法是GestureLibraries.fromFile(),除此方法外,还有其他方法,分别为从gesture路径(String)、File对象、从私有的gesture文件路径加载和从资源文件里加载gesture等,如表5-12所示。

表5-12                                                    gesture相关列表

static GestureLibrary

fromFile(String path)

static GestureLibrary

fromFile(File path)

static GestureLibrary

fromPrivateFile(Context context, String name)

static GestureLibrary

fromRawResource(Context context, int resourceId)

 

另一个扩展练习,通过读取/sdcard/gestures里方才建立的手写,并显示在ListView中,此扩展学习范例的关键程序,提示如下(详细解答可参考范例光盘):

 

/* 读取gesture信息的method */

private void loadGestures()

{

  gesNames=new ArrayList<String>();

  gesPics=new ArrayList<Bitmap>();

 

  try

  {

    lib = GestureLibraries.fromFile(gesFile);

    

    if(gesFile.exists())

    {

      /* 文件存在时先读取已存储的Gesture */

      if (!lib.load())

      {

        /* Library读取失败 */

        mEmpty.setText(getString(R.string.load_failed));

        mEmpty.setVisibility(EditText.VISIBLE);

      }

      else

      {

        /* 读取gesture信息 */

        Object[] en=lib.getGestureEntries().toArray();

        for(int i=0;i<en.length;i++)

        {

          ArrayList<Gesture> al=lib.getGestures(en[i].toString());

          for(int j=0;j<al.size();j++)

          {

            /* 手写名称 */

            gesNames.add(en[i].toString());

            Gesture gs=(Gesture)al.get(j);

            /* 将手写转成Bitmap图片 */

            gesPics.add(gs.toBitmap(64,64,12,Color.GREEN));

          }

        }

      }

    }

  }

  catch(Exception e)

  {

    e.printStackTrace();

  }

}

<!--[endif]-->

▲ 图5-29  读取/sdcard/gestures中已经建立的手写笔画并显示在ListView中

原创粉丝点击