andorid里的手势电话学习(上)

自己在学习手势Gesture绘制的时候突然想画一个爱心实现一键拨号给honey的应用,先在安卓巴士找了个手势电话案例结合android samples里的Gesture Builder改写了个画爱心拨通号码的应用,先把我在安卓巴士上看到的案例复制过来:

学习一下android中的手势文件。手势相关的类有
1.GestureOverlayView,这个是手势绘制区,既布局中的一个控件,用于接收用户绘制的手势、监听绘制区的改变、清除当前手势等等。
2.GestureLibrary 这个算是手势文件的一个库,里面存放着当前保存过的手势资源,可以用这个类进行手势资源的存储和读取。
3.Gesture,手势实例,无论是读取手势,还是要保存当前的手势,都是Gesture对象。
4.Prediction 识别率。主要用于在根据当前手势查询手势库中是否有匹配手势时需要用到。
下面根据程序来详细讲解一下如何应用这几个类。

本主要功能是根据手势判别来拨打电话。可以保存手势,查看现在保存的手势,如果程序第一次运行,便在指定路径下建立手势文件。

因为要保存手势文件和打电话,所以首先在程序清单中添加权限
AndroidManifest.xml代码片段:

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

程序用到的布局文件有4个,一个是主Activity用到的xml布局。就是第一张图的布局文件:
main.xml代码:

 1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:layout_width="fill_parent"
4 android:layout_height="fill_parent"
5 android:orientation="vertical" >
6
7 <TextView
8 android:layout_width="fill_parent"
9 android:layout_height="wrap_content"
10 android:text="@string/hello" />
11
12 <android.gesture.GestureOverlayView
13 android:id="@+id/gestures"
14 android:layout_width="fill_parent"
15 android:layout_height="fill_parent"
16 android:layout_weight="1"
17 android:gestureStrokeType="multiple" >
18 </android.gesture.GestureOverlayView>
19
20 <LinearLayout android:layout_width="fill_parent"
21 android:layout_height="wrap_content"
22 android:gravity="center_horizontal">
23 <Button
24 android:id="@+id/btnAdd"
25 android:layout_width="wrap_content"
26 android:layout_height="wrap_content"
27 android:text=" 添加手势 " />
28 <Button
29 android:id="@+id/btnSelect"
30 android:layout_width="wrap_content"
31 android:layout_height="wrap_content"
32 android:text="查看已有手势" />
33 </LinearLayout>
34
35 </LinearLayout>

以及添加手势资源时用的布局文件:
addgesture.xml

 1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:layout_width="fill_parent"
4 android:layout_height="fill_parent"
5 android:orientation="vertical"
6 android:gravity="center_horizontal">
7
8 <LinearLayout
9 android:layout_width="fill_parent"
10 android:layout_height="wrap_content" >
11
12 <TextView
13 android:layout_width="wrap_content"
14 android:layout_height="wrap_content"
15 android:text="手机号码:"
16 android:inputType="number"/>
17
18 <EditText
19 android:id="@+id/txtNum"
20 android:layout_width="match_parent"
21 android:layout_height="wrap_content" />
22 </LinearLayout>
23
24 <android.gesture.GestureOverlayView
25 android:id="@+id/gestureAdd"
26 android:layout_width="fill_parent"
27 android:layout_height="fill_parent"
28 android:layout_weight="1"
29 android:gestureStrokeType="multiple" >
30 </android.gesture.GestureOverlayView>
31
32 <Button
33 android:id="@+id/btnOK"
34 android:layout_width="wrap_content"
35 android:layout_height="wrap_content"
36 android:text=" 确定 " />
37
38 </LinearLayout>

剩下2个是gridView的布局文件和点击查看所有手势的布局文件:

 1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:layout_width="wrap_content"
4 android:layout_height="wrap_content"
5 android:orientation="vertical" android:gravity="center">
6 <ImageView android:id="@+id/itemIcon" android:layout_width="wrap_content"
7 android:layout_height="wrap_content" />
8 <TextView android:id="@+id/itemText" android:layout_width="wrap_content"
9 android:layout_height="wrap_content" android:textColor="#fff"/>
10
11 </LinearLayout>

 

 1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent"
5 android:orientation="vertical" >
6
7 <GridView
8 android:id="@+id/gvTop"
9 android:layout_width="fill_parent"
10 android:layout_height="fill_parent"
11 android:gravity="center"
12 android:numColumns="auto_fit"
13 android:scrollbars="none">
14 </GridView>
15
16 </LinearLayout>

在主activity GestureLearnActivity中,要判断第一次加载时是否有手势文件,如果没有则创建一个手势文件,并监听手势绘制区的改变,当绘制完成时与手势库中的手势进行比较。
GestureLearnActivity代码片段

 1 /**
2 * 初始化
3 */
4 public void init() {
5 // 获得布局中的组件
6 btnAdd = (Button) findViewById(R.id.btnAdd);
7 btnAdd.setOnClickListener(this);
8 btnSelect = (Button) findViewById(R.id.btnSelect);
9 btnSelect.setOnClickListener(this);
10 gesture = (GestureOverlayView) findViewById(R.id.gestures);
11 // 手势文件的加载路径
12 String path = "/sdcard/gestures";
13 // 加载手势文件
14 library = GestureLibraries.fromFile(path);
15 if (library.load()) {
16
17 gesture.addOnGesturePerformedListener(this);
18 } else {
19 Toast.makeText(GestureLearnActivity.this, "无手势文件",
20 Toast.LENGTH_LONG).show();
21
22 File file = new File(path);
23 try {
24 //创建手势文件
25 file.createNewFile();
26 } catch (Exception e) {
27 e.printStackTrace();
28 }
29 }
30 }
31 // 这个接口里处理匹配的手势
32 public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
33 ArrayList<Prediction> predictions = library.recognize(gesture);
34 if (predictions.size() > 0) {
35 // 获得识别率
36 Prediction predict = predictions.get(0);
37 // 如果识别率大于1,则说明找到匹配手势
38 if (predict.score > 1.0) {
39 //调用打电话activity
40 Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:"
41 + predict.name));
42 //不打电话,只进入打电话界面
43 //Intent phone=new Intent("com.android.phone.action.TOUCH_DIALER");
44 startActivity(intent);
45 }
46 }
47
48 }

剩下的就是查看手势文件了,这里我用到的是GridView控件来布局,将手势库中的文件都读取出来,由于是练习程序,所以没做复杂的操作,只是显示已经保存的手势文件。这里用到Gesture 的实例对象,通过这个对象将手势文件转换成位图来显示。
ListGestures.java代码片段

 1 public void load() {
2 String path = "/sdcard/gestures";
3 // 加载手势文件
4 library = GestureLibraries.fromFile(path);
5
6 if (library.load()) {
7 int index = library.getGestureEntries().size();
8 pics = new Bitmap[index];
9 gesName=new String[index];
10 int i = 0;
11 //获得所有手势文件,返回的是存储key的set集合
12 for (String name : library.getGestureEntries()) {
13 // 因为在手势仓库中,支持一个name对应多个手势文件,
14 // 所以会返回一个list,在这里我们取list里的第一个
15 ArrayList<Gesture> geess = library.getGestures(name);
16 Gesture gg = geess.get(0);
17 //将手势文件转成位图
18 Bitmap bmp = gg.toBitmap(100, 100, 12, Color.BLUE);
19 pics[i] = bmp;//保存位图
20 gesName[i]=name;//保存当前的手势名称。
21 i++;
22 }
23 }
24 }

最后的gridView的适配器代码就不多说了。直接上源码

 1 public class GridAdapter extends BaseAdapter {
2 // 每个gridItem显示的值
3 private Context mContext;
4 private LayoutInflater mInflater;
5
6 public GridAdapter(Context context) {
7 mContext = context;
8 mInflater = (LayoutInflater) context
9 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
10
11 }
12
13 public int getCount() {
14 // 返回适配器中数据的数量
15 return ListGestures.pics.length;
16 }
17
18 public Object getItem(int position) {
19 // 用不到
20 return null;
21 }
22
23 public long getItemId(int position) {
24 // 用不到
25 return 0;
26 }
27
28 // 此方法的convertView是在grid_item里定义的组件。这里是一个ImageView和TextView
29 public View getView(int position, View convertView, ViewGroup parent) {
30 if (convertView == null) {
31 convertView = mInflater.inflate(R.layout.grid_item, null);
32 }
33 ImageView icon = (ImageView) convertView.findViewById(R.id.itemIcon);
34 TextView text = (TextView) convertView.findViewById(R.id.itemText);
35 icon.setImageBitmap(ListGestures.pics[position]);
36 text.setText(ListGestures.gesName[position]);
37 return convertView;// 返回已经改变过的convertView,节省系统资源
38 }
39
40 }

OK,这些就是实现这个程序的主要代码,程序在运行后,会根据当前的绘制手势匹配库中的手势,如果匹配成功,就会调用打电话的activity。后面附上源代码,感兴趣的可以下载了以后去运行并查看完整的代码,记得是在真机上运行哦。因为我直接访问的SD卡,模拟器上运行可能会出错。下一得晚上将自己的再挂出来。

完整代码我已放网盘:http://dl.dbank.com/c000mayxox

 

posted @ 2012-04-05 15:00  落尘祥  阅读(1740)  评论(3编辑  收藏  举报