最近写了一个小程序,学习了一下android中的手势文件。手势相关的类有
1.GestureOverlayView,这个是手势绘制区,既布局中的一个控件,用于接收用户绘制的手势、监听绘制区的改变、清除当前手势等等。
2.GestureLibrary 这个算是手势文件的一个库,里面存放着当前保存过的手势资源,可以用这个类进行手势资源的存储和读取。
3.Gesture,手势实例,无论是读取手势,还是要保存当前的手势,都是Gesture对象。
4.Prediction 识别率。主要用于在根据当前手势查询手势库中是否有匹配手势时需要用到。
下面根据程序来详细讲解一下如何应用这几个类。
本主要功能是根据手势判别来拨打电话。可以保存手势,查看现在保存的手势,如果程序第一次运行,便在指定路径下建立手势文件。
因为要保存手势文件和打电话,所以首先在程序清单中添加权限
AndroidManifest.xml代码片段:
复制代码
程序用到的布局文件有4个,一个是主Activity用到的xml布局。就是第一张图的布局文件:
main.xml代码:
复制代码
以及添加手势资源时用的布局文件:
addgesture.xml
复制代码
剩下2个是gridView的布局文件和点击查看所有手势的布局文件:
复制代码
复制代码
在主activity GestureLearnActivity中,要判断第一次加载时是否有手势文件,如果没有则创建一个手势文件,并监听手势绘制区的改变,当绘制完成时与手势库中的手势进行比较。
GestureLearnActivity代码片段
复制代码
在点击添加手势按钮以后,程序进入第二个activity中
GestureLearnActivity代码片段:
复制代码
添加手势的activity中实现添加手势绘制区的监听,需要实现4个方法
AddGesture代码片段:
复制代码
剩下的就是查看手势文件了,这里我用到的是GridView控件来布局,将手势库中的文件都读取出来,由于是练习程序,所以没做复杂的操作,只是显示已经保存的手势文件。这里用到Gesture 的实例对象,通过这个对象将手势文件转换成位图来显示。
ListGestures.java代码片段
复制代码
最后的gridView的适配器代码就不多说了。直接上源码
复制代码
1.GestureOverlayView,这个是手势绘制区,既布局中的一个控件,用于接收用户绘制的手势、监听绘制区的改变、清除当前手势等等。
2.GestureLibrary 这个算是手势文件的一个库,里面存放着当前保存过的手势资源,可以用这个类进行手势资源的存储和读取。
3.Gesture,手势实例,无论是读取手势,还是要保存当前的手势,都是Gesture对象。
4.Prediction 识别率。主要用于在根据当前手势查询手势库中是否有匹配手势时需要用到。
下面根据程序来详细讲解一下如何应用这几个类。
本主要功能是根据手势判别来拨打电话。可以保存手势,查看现在保存的手势,如果程序第一次运行,便在指定路径下建立手势文件。
因为要保存手势文件和打电话,所以首先在程序清单中添加权限
AndroidManifest.xml代码片段:
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.CALL_PHONE"/>
main.xml代码:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <TextView
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="@string/hello" />
- <android.gesture.GestureOverlayView
- android:id="@+id/gestures"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:layout_weight="1"
- android:gestureStrokeType="multiple" >
- </android.gesture.GestureOverlayView>
- <LinearLayout android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal">
- <Button
- android:id="@+id/btnAdd"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text=" 添加手势 " />
- <Button
- android:id="@+id/btnSelect"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="查看已有手势" />
- </LinearLayout>
- </LinearLayout>
addgesture.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- android:gravity="center_horizontal">
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" >
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="手机号码:"
- android:inputType="number"/>
- <EditText
- android:id="@+id/txtNum"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
- </LinearLayout>
- <android.gesture.GestureOverlayView
- android:id="@+id/gestureAdd"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:layout_weight="1"
- android:gestureStrokeType="multiple" >
- </android.gesture.GestureOverlayView>
- <Button
- android:id="@+id/btnOK"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text=" 确定 " />
- </LinearLayout>
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- android:gravity="center_horizontal">
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" >
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="手机号码:"
- android:inputType="number"/>
- <EditText
- android:id="@+id/txtNum"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
- </LinearLayout>
- <android.gesture.GestureOverlayView
- android:id="@+id/gestureAdd"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:layout_weight="1"
- android:gestureStrokeType="multiple" >
- </android.gesture.GestureOverlayView>
- <Button
- android:id="@+id/btnOK"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text=" 确定 " />
- </LinearLayout>
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
- <GridView
- android:id="@+id/gvTop"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:gravity="center"
- android:numColumns="auto_fit"
- android:scrollbars="none">
- </GridView>
- </LinearLayout>
GestureLearnActivity代码片段
- /**
- * 初始化
- */
- public void init() {
- // 获得布局中的组件
- btnAdd = (Button) findViewById(R.id.btnAdd);
- btnAdd.setOnClickListener(this);
- btnSelect = (Button) findViewById(R.id.btnSelect);
- btnSelect.setOnClickListener(this);
- gesture = (GestureOverlayView) findViewById(R.id.gestures);
- // 手势文件的加载路径
- String path = "/sdcard/gestures";
- // 加载手势文件
- library = GestureLibraries.fromFile(path);
- if (library.load()) {
-
- gesture.addOnGesturePerformedListener(this);
- } else {
- Toast.makeText(GestureLearnActivity.this, "无手势文件",
- Toast.LENGTH_LONG).show();
-
- File file = new File(path);
- try {
- //创建手势文件
- file.createNewFile();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- // 这个接口里处理匹配的手势
- public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
- ArrayList<Prediction> predictions = library.recognize(gesture);
- if (predictions.size() > 0) {
- // 获得识别率
- Prediction predict = predictions.get(0);
- // 如果识别率大于1,则说明找到匹配手势
- if (predict.score > 1.0) {
- //调用打电话activity
- Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:"
- + predict.name));
- //不打电话,只进入打电话界面
- //Intent phone=new Intent("com.android.phone.action.TOUCH_DIALER");
- startActivity(intent);
- }
- }
- }
GestureLearnActivity代码片段:
- case R.id.btnAdd:// 处理按下添加手势按钮
- Intent intent = new Intent(getApplicationContext(),
- AddGesture.class);
- startActivity(intent);
- //切换activity动画
- overridePendingTransition(android.R.anim.slide_in_left, android.R.anim.slide_in_left);
-
- break;
AddGesture代码片段:
- /**
- * 处理监听,初始化组件
- */
- public void init() {
- gestureNew = (GestureOverlayView) findViewById(R.id.gestureAdd);
- txtNum = (EditText) findViewById(R.id.txtNum);
- btnOk = (Button) findViewById(R.id.btnOK);
- btnOk.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- // 返回按钮。
- finish();
- }
- });
- // 添加手势绘制区的监听,需要实现4个方法
- gestureNew
- .addOnGestureListener(new GestureOverlayView.OnGestureListener() {
- // 开始绘制时调用
- public void onGestureStarted(GestureOverlayView overlay,
- MotionEvent event) {
- }
- // 以下方法是当手势完整形成的时候触发,主要处理在这个方法中实现
- public void onGestureEnded(GestureOverlayView overlay,
- MotionEvent event) {
- Log.e("sc", "进入绘制完成");
- gesture = overlay.getGesture();
- //如果没有输入
- if (txtNum.getText().toString().equals("")) {
- Toast.makeText(AddGesture.this, "请输入号码",
- Toast.LENGTH_LONG).show();
- txtNum.setFocusable(true);
- gestureNew.clear(true);
- }
- //利用正则表达试判断输入
- else if (!(txtNum.getText().toString()
- .matches("[0-9]*"))) {
- Toast.makeText(AddGesture.this, "输入的必须是数字",
- Toast.LENGTH_LONG).show();
- txtNum.setFocusable(true);
- } else {
- // 读取文件
- libraryNew = GestureLibraries
- .fromFile("/sdcard/gestures");
- Log.e("sc", "读取文件完毕" + libraryNew.toString());
- libraryNew.load();
- // 给手势仓库添加当前的手势
- libraryNew.addGesture(txtNum.getText().toString(),
- gesture);
- if (libraryNew.save())// 保存
- {
- gestureNew.clear(true);// 清除笔画
- Toast.makeText(AddGesture.this, "保存成功!",
- Toast.LENGTH_LONG).show();
- } else {
- Toast.makeText(AddGesture.this, "保存失败",
- Toast.LENGTH_LONG).show();
- }
- }
- }
- public void onGestureCancelled(GestureOverlayView overlay,
- MotionEvent event) {
- // TODO Auto-generated method stub
- }
- public void onGesture(GestureOverlayView overlay,
- MotionEvent event) {
- // TODO Auto-generated method stub
- }
- });
- }
ListGestures.java代码片段
- public void load() {
- String path = "/sdcard/gestures";
- // 加载手势文件
- library = GestureLibraries.fromFile(path);
- if (library.load()) {
- int index = library.getGestureEntries().size();
- pics = new Bitmap[index];
- gesName=new String[index];
- int i = 0;
- //获得所有手势文件,返回的是存储key的set集合
- for (String name : library.getGestureEntries()) {
- // 因为在手势仓库中,支持一个name对应多个手势文件,
- // 所以会返回一个list,在这里我们取list里的第一个
- ArrayList<Gesture> geess = library.getGestures(name);
- Gesture gg = geess.get(0);
- //将手势文件转成位图
- Bitmap bmp = gg.toBitmap(100, 100, 12, Color.BLUE);
- pics[i] = bmp;//保存位图
- gesName[i]=name;//保存当前的手势名称。
- i++;
- }
- }
- }
- public class GridAdapter extends BaseAdapter {
- // 每个gridItem显示的值
- private Context mContext;
- private LayoutInflater mInflater;
- public GridAdapter(Context context) {
- mContext = context;
- mInflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- }
- public int getCount() {
- // 返回适配器中数据的数量
- return ListGestures.pics.length;
- }
- public Object getItem(int position) {
- // 用不到
- return null;
- }
- public long getItemId(int position) {
- // 用不到
- return 0;
- }
- // 此方法的convertView是在grid_item里定义的组件。这里是一个ImageView和TextView
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = mInflater.inflate(R.layout.grid_item, null);
- }
- ImageView icon = (ImageView) convertView.findViewById(R.id.itemIcon);
- TextView text = (TextView) convertView.findViewById(R.id.itemText);
- icon.setImageBitmap(ListGestures.pics[position]);
- text.setText(ListGestures.gesName[position]);
- return convertView;// 返回已经改变过的convertView,节省系统资源
- }
- }