[转载]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