Android手机手势示例
android的手机主要以触摸屏为主,为了能够让用户体验到更多的手指滑动屏幕的乐趣,android提供了一套自己的手指滑动判断事件类。GestureDetector翻译成中文就是发现手势,专业术语叫做手势检测类。Detects various gestures and events using the supplied MotionEvents. 这是摘自android的API上面的一句话,意思就是 用提供给GestureDetector的事件检测手势和事件。
大概思想就是创建GestureDetector,这个类没有无参的构造,更加详细的构造API上有。这里用的是 GestureDetector(GestureDetector.OnGestureListener listener)这个构造方法,传进去OnGestutre类型,再提供给它一个MotionEvent事件让Gesture自己去分析应该回调哪个函数。
在回调函数里面写自己的想法,一共有五个经常用的回调函数。
onDown,只要检测到手指触到屏幕了不管手指有没有拿起来都至少会调用一次onDown或者多次onDown函数。
onFling,专业的检测手指滑动事件就会调用该函数。
onLongPress,手指长按的时候就会调用该函数。
onScroll,这个函数需要跟onFling区别开来,这俩玩意个人感觉唯一的区别就是速度上的快慢而调用不同函数,onFling,正在飞,onScroll,正在滚,具体速度是多少才能区分出俩函数还需要更多的测试。
onShowPress,android的API上如是说:用户的手指触摸到屏幕了既没有移动也没有拿开的时候会调用该函数,这就需要跟onDown函数有点区分。onDown传进来的MotionEvent是down那就调用onDown,这都是API上的大概意思。
onSingleTapUp,当手指按下屏幕,并且检测到传进来的MotionEvent是up则调用该函数。
多说无益直接写例子自己亲身感受这些函数之间的细微区别。还是毛嗲嗲说的好,实践出真知。这个例子是借鉴的网上某某的思想结合在hrd里面的做法写的例子,通过这个例子可以完整的看到当gestureDetector检测到什么操作的时候会调用神马函数。直接贴代码直接运行的
Activity代码,整个测试程序只有一个Activity
package opq.movcircle; import android.app.Activity; import android.os.Bundle; import android.view.Display; public class MainCircle extends Activity { /** Called when the activity is first created. */ CircleView circleView; public static int scWidth; public static int scHeight; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Display display = getWindowManager().getDefaultDisplay(); scWidth= display.getWidth();//得到屏幕宽 scHeight= display.getHeight();//得到屏幕高 circleView=new CircleView(this);//创建绘图类 setContentView(circleView); } } CircleView中的代码,这个类继承自surface类,专门用来画图的类和实现俩接口:
package opq.movcircle; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.util.Log; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.View.OnTouchListener; public class CircleView extends SurfaceView implements OnTouchListener,SurfaceHolder.Callback { MainCircle main; Paint paint; CircleViewDrawThread circleViewDrawThread; GestureDetector gestureDetector; public static float circleX=200;//得到 x坐标 用于改变圆的坐标 public static float circleY=200;//同上 /*这些个变量的作用是 初始化的时候都为false 当对应的方法调用之后给它设为true * 在onDraw方法里面判断 显示哪些方法被调用了哪些方法没被调用 * 规则if后面都是对应的回调函数名 * */ public static boolean ifOnDoubleTap=false; public static boolean ifOnDoubleTapEvent=false; public static boolean ifOnDown=false; public static boolean ifOnFling=false; public static boolean ifOnLongPress=false; public static boolean ifOnScroll=false; public static boolean ifOnShowPress=false; public static boolean ifOnSingleTapConfirmed=false; public static boolean ifOnSingleTapUp=false; public static boolean ifFingerUp; public CircleView(MainCircle main){ super(main); this.main=main; getHolder().addCallback(this); circleViewDrawThread=new CircleViewDrawThread(this,getHolder()); paint=new Paint();//绘图对象 paint.setColor(Color.RED);//设置为红色 paint.setTextSize(20);//如果画字体,设置字体大小 gestureDetector=new GestureDetector(new CircleViewGestureListener());//创建手势检测类 this.setOnTouchListener(this); this.setFocusable(true); this.setClickable(true); this.setLongClickable(true); } public boolean onTouch(View v, MotionEvent event) { if(event.getAction()==event.ACTION_UP){//当手指离开屏幕的时候 所有的判断方法变量全部初始化 ifFingerUp=false; ifOnDoubleTap=false; ifOnDoubleTapEvent=false; ifOnDown=false; ifOnFling=false; ifOnLongPress=false; ifOnScroll=false; ifOnShowPress=false; ifOnSingleTapConfirmed=false; ifOnSingleTapUp=false; } return gestureDetector.onTouchEvent(event); } @Override protected void onDraw(Canvas canvas) { canvas.drawColor(Color.BLACK);//画黑色相当于更新画布 /* 如果调用了onDown方法 ifOndown就为true 否则绘制else 后面的以此类推*/ if(ifOnDown){canvas.drawText("onDown=true",0,0, paint);}else{canvas.drawText("onDown=false",0,0, paint);} if(ifOnDoubleTap){canvas.drawText("onDoubleTap=true",0,20, paint);}else{canvas.drawText("onDoubleTap=false",0,20, paint);} if(ifOnDoubleTapEvent){canvas.drawText("onDoubleTapEvent=true",0,40, paint);}else{canvas.drawText("onDoubleTapEvent=false",0,40, paint);} if(ifOnDown){canvas.drawText("onDown=true",0,60, paint);}else{canvas.drawText("onDown=false",0,60, paint);} if(ifOnFling){canvas.drawText("onFling=true",0,80, paint);}else{canvas.drawText("onFling=false",0,80, paint);} if(ifOnLongPress){canvas.drawText("onLongPress=true",0,100, paint);}else{canvas.drawText("onLongPress=false",0,100, paint);} if(ifOnScroll){canvas.drawText("onScroll=true",0,120, paint);}else{canvas.drawText("onScroll=false",0,120, paint);} if(ifOnShowPress){canvas.drawText("onShowPress=true",0,140, paint);}else{canvas.drawText("onShowPress=false",0,140, paint);} if(ifOnSingleTapConfirmed){canvas.drawText("ifOnSingleTapConfirmed=true",0,160, paint);}else{canvas.drawText("ifOnSingleTapConfirmed=false",0,160, paint);} if(ifOnSingleTapUp){canvas.drawText("ifOnSingleTapUp=true",0,180, paint);}else{canvas.drawText("ifOnSingleTapUp=false",0,180, paint);} canvas.drawLine(circleX,0,circleX,MainCircle.scHeight, paint); canvas.drawLine(0,circleY,MainCircle.scWidth,circleY, paint); canvas.drawCircle(circleX,circleY,50, paint); } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { circleViewDrawThread.setFlag(true); circleViewDrawThread.start();//线程开始刷帧 } public void surfaceCreated(SurfaceHolder holder) { } public void surfaceDestroyed(SurfaceHolder holder) { } class CircleViewGestureListener extends GestureDetector.SimpleOnGestureListener{//手势类 @Override public boolean onDoubleTap(MotionEvent e) { Log.d("DEBUGMSG","onDoubleTap"); CircleView.ifOnDoubleTap=true; return super.onDoubleTap(e); } @Override public boolean onDoubleTapEvent(MotionEvent e) { Log.d("DEBUGMSG","onDoubleTapEvent"); CircleView.this.ifOnDoubleTapEvent=true; return super.onDoubleTapEvent(e); } @Override public boolean onDown(MotionEvent e) { Log.d("DEBUGMSG","onDown"); CircleView.this.ifOnDown=true; return super.onDown(e); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { CircleView.this.ifOnFling=true; Log.d("DEBUGMSG","onFling"); return super.onFling(e1, e2, velocityX, velocityY); } @Override public void onLongPress(MotionEvent e) { CircleView.this.ifOnLongPress=true; Log.d("DEBUGMSG","onLongPress"); super.onLongPress(e); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { Log.d("DEBUGMSG","onScroll"); CircleView.this.ifOnScroll=true; CircleView.this.circleX=e2.getX();CircleView.this.circleY=e2.getY(); return super.onScroll(e1, e2, distanceX, distanceY); } @Override public void onShowPress(MotionEvent e) { Log.d("DEBUGMSG","onShowPress"); CircleView.this.ifOnShowPress=true; super.onShowPress(e); } @Override public boolean onSingleTapConfirmed(MotionEvent e) { Log.d("DEBUGMSG","onSingleTapConfirmed"); CircleView.this.ifOnSingleTapConfirmed=true; return super.onSingleTapConfirmed(e); } @Override public boolean onSingleTapUp(MotionEvent e) { Log.d("DEBUGMSG","onSingleTapUp"); CircleView.this.ifOnSingleTapUp=true; return super.onSingleTapUp(e); } } } 最后一个是画图的刷帧线程
package opq.movcircle; import android.graphics.Canvas; import android.util.Log; import android.view.SurfaceHolder; public class CircleViewDrawThread extends Thread { CircleView circleView; SurfaceHolder surfaceHolder; int sleepSpan = 10;//睡眠的毫秒数 public boolean flag;//是否刷帧 public CircleViewDrawThread(CircleView circleView,SurfaceHolder surfaceHolder){ this.circleView=circleView; this.surfaceHolder=surfaceHolder; } public CircleViewDrawThread(){} @Override public void run() { Canvas c;//画布 while(flag){ c = null; try { c = surfaceHolder.lockCanvas(null); synchronized (this.surfaceHolder) { try{ circleView.onDraw(c); } catch(Exception e){} } } finally { if (c != null) { surfaceHolder.unlockCanvasAndPost(c); } } try{ Thread.sleep(sleepSpan);//睡眠 } catch(Exception e){ e.printStackTrace(); } } } public void setFlag(boolean flag){ this.flag=flag; } }