1. 接触接触屏一刹那,触发一个MotionEvent事件。
2. 该事件被OnTouchListener监听,在其onTouch()方法里获得该MotionEvent对象。
3. 通过GestureDetector(手势识别器)转发次MotionEvent对象至OnGestureListener。
4. OnGestureListener获得该对象,听根据该对象封装的的信息,做出合适的反馈。
这个顺序可以说就是手势交互的原理,下面一同来了解一下MotionEvent、GestureDetector和OnGestureListener。
MotionEvent: 这个类用于封装手势、触摸笔、轨迹球等等的动作事件。其内部封装了两个重要的属性X和Y,这两个属性分别用于记录横轴和纵轴的坐标。
GestureDetector: 识别各种手势。
OnGestureListener: 这是一个手势交互的监听接口,其中提供了多个抽象方法,并根据GestureDetector的手势识别结果调用相对应的方法。
参考代码如下
package hfut.gmm; import java.util.ArrayList; import android.app.Activity; import android.gesture.Gesture; import android.gesture.GestureLibraries; import android.gesture.GestureLibrary; import android.gesture.GestureOverlayView; import android.gesture.Prediction; import android.gesture.GestureOverlayView.OnGesturePerformedListener; import android.os.Bundle; import android.util.Log; import android.view.ContextMenu; import android.view.GestureDetector; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.Window; import android.view.ContextMenu.ContextMenuInfo; import android.view.GestureDetector.OnGestureListener; import android.view.View.OnTouchListener; import android.view.ViewGroup.LayoutParams; import android.view.animation.AnimationUtils; import android.widget.ImageSwitcher; import android.widget.ImageView; import android.widget.Toast; import android.widget.ViewSwitcher.ViewFactory; public class MainActivity extends Activity implements ViewFactory, OnTouchListener, OnGestureListener { /** Called when the activity is first created. */ private ImageSwitcher imgswitcher; private Integer[] pics = { R.drawable.pic_one, R.drawable.pic_two, R.drawable.pic_three, R.drawable.pic_four, R.drawable.pic_five,R.drawable.pic_six, R.drawable.pic_seven }; int index; private boolean success; private GestureDetector detector ; GestureLibrary library; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.main); detector=new GestureDetector(this); imgswitcher=(ImageSwitcher)this.findViewById(R.id.imageSwitcher1); imgswitcher.setFactory(this); imgswitcher.setInAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in)); imgswitcher.setOutAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out)); imgswitcher.setImageResource(pics[2]); imgswitcher.setOnTouchListener(this); imgswitcher.setLongClickable(true); detector.setIsLongpressEnabled(true);//Set whether longpress is enabled this.registerForContextMenu(this.findViewById(R.id.textView1)); library = GestureLibraries.fromRawResource(this, R.raw.gestures); //加载手势库 success = library.load(); //找到手势识别控件 GestureOverlayView gestureView = (GestureOverlayView)this.findViewById(R.id.gestures); gestureView.addOnGesturePerformedListener(new GestureListener()); } //手势识别监听... class GestureListener implements OnGesturePerformedListener { @Override public void onGesturePerformed(GestureOverlayView arg0, Gesture gesture) { // TODO Auto-generated method stub if(success) { //从手势库中查找匹配的手势,最匹配的记录会放在最前面 ArrayList<Prediction> predictions = library.recognize(gesture); if(!predictions.isEmpty()) { Prediction prediction = predictions.get(0); //Log中显示出匹配程度 Log.i("Infor", "score:"+ prediction.score); //匹配程度大于30% if(prediction.score>3) { //这是关闭的手势 if("question".equals(prediction.name)) { Toast.makeText(MainActivity.this, "当前手势:question", Toast.LENGTH_LONG).show(); } } } } } } public void nextgirl(){ index++; imgswitcher.setImageResource(pics[index%pics.length]); } public void pregirl(){ index--; if(index==-1) index=pics.length-1; imgswitcher.setImageResource(pics[index%pics.length]); } @Override public View makeView() { // TODO Auto-generated method stub ImageView i = new ImageView(this); i.setBackgroundColor(0xFF011000); i.setScaleType(ImageView.ScaleType.FIT_XY); i.setLayoutParams(new ImageSwitcher.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); return i; } @Override public boolean onTouch(View arg0, MotionEvent arg1) { // TODO Auto-generated method stub detector.onTouchEvent(arg1); //将motionEvent事件添加进GestureDetector进行监听处理 return true; } @Override public boolean onDown(MotionEvent arg0) { // TODO Auto-generated method stub Log.d("Infor", "onDown被调用..."); return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // TODO Auto-generated method stub if(velocityX<0) nextgirl(); else if(velocityX>0) pregirl(); Log.d("Infor", "onFling被用调用"); return false; } @Override public void onLongPress(MotionEvent arg0) { // TODO Auto-generated method stub Log.d("Infor", "长按"); } @Override public boolean onScroll(MotionEvent arg0, MotionEvent arg1, float arg2, float arg3) { // TODO Auto-generated method stub Log.d("Infor", "onScroll被用调用"); return false; } @Override public void onShowPress(MotionEvent arg0) { // TODO Auto-generated method stub Log.d("Infor", "onShowPress被用调用"); } @Override public boolean onSingleTapUp(MotionEvent arg0) { // TODO Auto-generated method stub Log.d("Infor", "onSingleTapUp被用调用"); return false; } //上下文菜单.... public boolean onContextItemSelected(MenuItem item) { // TODO Auto-generated method stub return super.onContextItemSelected(item); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { // TODO Auto-generated method stub super.onCreateContextMenu(menu, v, menuInfo); menu.add(0,Menu.FIRST, 0, "菜单"); } }xml文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:weightSum="1"> <TextView android:text="TextView" android:layout_height="wrap_content" android:id="@+id/textView1" android:layout_width="match_parent"></TextView> <ImageSwitcher android:layout_width="match_parent" android:id="@+id/imageSwitcher1" android:layout_height="wrap_content" android:layout_weight="0.61"></ImageSwitcher> <!--添加手势识别的控件 --> <android.gesture.GestureOverlayView android:layout_width="fill_parent" android:layout_height="0dip" android:gestureStrokeType="multiple" android:id="@+id/gestures" android:layout_weight="1.24"/> </LinearLayout>上述代码主要实现两个功能:
1、手势交互功能
通过一个imageSwitcher对它进行左右滑动切换图片从而可以实现类似翻页功能....
2、手势识别功能(红体字标识)
通过使用Android SDK samples里面自带的GestureBuilder建立手势库(位置:android-sdk-windows/samples/android-8/GestureBuilder),运行就可以使用GestureBuilder建立手势库,生成的手势库文件在SCDard根目录下,默认文件名称为:gestures
把手势库文件gestures文件拷贝到项目的res/raw目录下。然后在布局文件中添加用于手势绘制的View:
PS:由于布局存在些许BUG,可能调试的时候无法两个功能同时显示,所以可以一个功能一个功能的调试.实现demo
参考博文:http://blog.csdn.net/kesenhoo/article/details/6550849
http://www.cnblogs.com/wisekingokok/archive/2011/08/30/2158358.html