Android 的触摸事件详解及示例代码
由于触摸(Touch)而触发的事件
Android的事件:onClick,onScroll,onFling等等,都是由许多个Touch组成的。其中Touch的第一个状态肯定是ACTION_DOWN,表示按下了屏幕。之后,touch将会有后续事件,可能是:
ACTION_MOVE//表示为移动手势
ACTION_UP//表示为离开屏幕
ACTION_CANCEL//表示取消手势,不会由用户产生,而是由程序产生的
一个Action_DOWN,n个ACTION_MOVE,1个ACTION_UP,就构成了Android中众多的事件。
对于ViewGroup类的控件,有一个很重要的方法,就是onInterceptTouchEvent(),用于处理事件并改变事件的传递方向,它的返回值是一个布尔值,决定了Touch事件是否要向它包含的子View继续传递,这个方法是从父View向子View传递。
而方法onTouchEvent(),用于接收事件并处理,它的返回值也是一个布尔值,决定了事件及后续事件是否继续向上传递,这个方法是从子View向父View传递。
touch事件在onInterceptTouchEvent()和onTouchEvent以及各个childView间的传递机制完全取决于onInterceptTouchEvent()和onTouchEvent()的返回值。返回值为true表示事件被正确接收和处理了,返回值为false表示事件没有被处理,将继续传递下去。
ACTION_DOWN事件会传到某个ViewGroup类的onInterceptTouchEvent,如果返回false,则DOWN事件继续向子ViewGroup类的onInterceptTouchEvent传递,如果子View不是ViewGroup类的控件,则传递给它的onTouchEvent。
如果onInterceptTouchEvent返回了true,则DOWN事件传递给它的onTouchEvent,不再继续传递,并且之后的后续事件也都传递给它的onTouchEvent。
如果某View的onTouchEvent返回了false,则DOWN事件继续向其父ViewGroup类的onTouchEvent传递;如果返回了true,则后续事件会直接传递给其onTouchEvent继续处理。(后续事件只会传递给对于必要事件ACTION_DOWN返回了true的onTouchEvent)
总结一下就是:onInterceptTouchEvent可以接受到所有的Touch事件,而onTouchEvent则不一定。
对于android自定义控件的事件android提供了一个GestureDetector的类和GestureDetector.OnGestureListener的接口来判断用户在界面上做出怎么样的动作。
Android里有两个类
android.view.GestureDetector
android.view.GestureDetector.SimpleOnGestureListener
(另外android.widget.Gallery好像是更牛x的OnGestureListener)
1)新建一个类继承SimpleOnGestureListener,HahaGestureDetectorListener
可以实现以下event事件。
booleanonDoubleTap(MotionEvente)
解释:双击的第二下Touchdown时触发
booleanonDoubleTapEvent(MotionEvente)
解释:双击的第二下Touchdown和up都会触发,可用e.getAction()区分。
booleanonDown(MotionEvente)
解释:Touchdown时触发
booleanonFling(MotionEvente1,MotionEvente2,floatvelocityX,floatvelocityY)
解释:Touch了滑动一点距离后,up时触发。
voidonLongPress(MotionEvente)
解释:Touch了不移动一直Touchdown时触发
booleanonScroll(MotionEvente1,MotionEvente2,floatdistanceX,floatdistanceY)
解释:Touch了滑动时触发。
voidonShowPress(MotionEvente)
解释:Touch了还没有滑动时触发
(与onDown,onLongPress比较
onDown只要Touchdown一定立刻触发。
而Touchdown后过一会没有滑动先触发onShowPress再是onLongPress。
所以Touchdown后一直不滑动,onDown->onShowPress->onLongPress这个顺序触发。
)
booleanonSingleTapConfirmed(MotionEvente)
booleanonSingleTapUp(MotionEvente)
解释:上面这两个函数都是在touchdown后又没有滑动(onScroll),又没有长按(onLongPress),然后Touchup时触发。
点击一下非常快的(不滑动)Touchup:
onDown->onSingleTapUp->onSingleTapConfirmed
点击一下稍微慢点的(不滑动)Touchup:
onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed
publicclassGestureActivityextendsActivityimplementsOnTouchListener, OnGestureListener{ GestureDetectordetector; publicGestureActivity(){ detector=newGestureDetector(this); } publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); TextViewtv=(TextView)findViewById(R.id.TextView001); //设置tv的监听器 tv.setOnTouchListener(this); tv.setFocusable(true); //必须,view才能够处理不同于Tap(轻触)的hold tv.setClickable(true); tv.setLongClickable(true); detector.setIsLongpressEnabled(true); } publicbooleanonTouch(Viewv,MotionEventevent){ returndetector.onTouchEvent(event); } //用户轻触触摸屏,由1个MotionEventACTION_DOWN触发 publicbooleanonDown(MotionEventarg0){ Log.i("MyGesture","onDown"); Toast.makeText(this,"onDown",Toast.LENGTH_SHORT).show(); returntrue; } publicvoidonShowPress(MotionEvente){ Log.i("MyGesture","onShowPress"); Toast.makeText(this,"onShowPress",Toast.LENGTH_SHORT).show(); } //用户(轻触触摸屏后)松开,由一个1个MotionEventACTION_UP触发 publicbooleanonSingleTapUp(MotionEvente){ Log.i("MyGesture","onSingleTapUp"); Toast.makeText(this,"onSingleTapUp",Toast.LENGTH_SHORT).show(); returntrue; } //用户按下触摸屏、快速移动后松开,由1个MotionEventACTION_DOWN,多个ACTION_MOVE,1个ACTION_UP触发 publicbooleanonFling(MotionEvente1,MotionEvente2,floatvelocityX,floatvelocityY){ Log.i("MyGesture","onFling"); //参数解释: //e1:第1个ACTION_DOWNMotionEvent //e2:最后一个ACTION_MOVEMotionEvent //velocityX:X轴上的移动速度,像素/秒 //velocityY:Y轴上的移动速度,像素/秒 //触发条件: //X轴的坐标位移大于FLING_MIN_DISTANCE,且移动速度大于FLING_MIN_VELOCITY个像素/秒 finalintFLING_MIN_DISTANCE=100,FLING_MIN_VELOCITY=200; if(e1.getX()-e2.getX()>FLING_MIN_DISTANCE&&Math.abs(velocityX)>FLING_MIN_VELOCITY){ //Flingleft Log.i("MyGesture","Flingleft"); Toast.makeText(this,"FlingLeft",Toast.LENGTH_SHORT).show(); }elseif(e2.getX()-e1.getX()>FLING_MIN_DISTANCE&&Math.abs(velocityX)>FLING_MIN_VELOCITY){ //Flingright Log.i("MyGesture","Flingright"); Toast.makeText(this,"FlingRight",Toast.LENGTH_SHORT).show(); }elseif(e2.getY()-e1.getY()>FLING_MIN_DISTANCE&&Math.abs(velocityY)>FLING_MIN_VELOCITY){ //Flingdown Log.i("MyGesture","Flingdown"); Toast.makeText(this,"Flingdown",Toast.LENGTH_SHORT).show(); }elseif(e1.getY()-e2.getY()>FLING_MIN_DISTANCE&&Math.abs(velocityY)>FLING_MIN_VELOCITY){ //Flingup Log.i("MyGesture","Flingup"); Toast.makeText(this,"Flingup",Toast.LENGTH_SHORT).show(); } returnfalse; } //用户按下触摸屏,并拖动,由1个MotionEventACTION_DOWN,多个ACTION_MOVE触发 publicbooleanonScroll(MotionEvente1,MotionEvente2,floatdistanceX,floatdistanceY){ Log.i("MyGesture","onScroll"); Toast.makeText(this,"onScroll",Toast.LENGTH_LONG).show(); returntrue; } //用户长按触摸屏,由多个MotionEventACTION_DOWN触发 publicvoidonLongPress(MotionEvente){ Log.i("MyGesture","onLongPress"); Toast.makeText(this,"onLongPress",Toast.LENGTH_LONG).show(); } }
2)在view的新建一个GestureDetector的对象。
构造函数里
gestureDetector=newGestureDetector(newHahaGestureDetectorListener());
然后在View的onTouchEvent里以下这样用,就可以在刚才1)弄的事件里写自己的代码了。
@Override publicbooleanonTouchEvent(MotionEventevent){ gestureDetector.onTouchEvent(event); } mTouchListener=newOnTouchListener(){ @Override publicbooleanonTouch(Viewv,MotionEventevent){ //TODOAuto-generatedmethodstub floatx=event.getXPrecision()*event.getX()+event.getX(); floaty=event.getYPrecision()*event.getY()+event.getY(); switch(event.getAction()){ caseMotionEvent.ACTION_DOWN: break; caseMotionEvent.ACTION_MOVE: mTouchTimes++; if(mTouchTimes>TOUCH_TIMES){ //根据方向计算角度 if(mCurrentOrientation==DeviceOrientation.Landscape){ mAngle=Math.toDegrees(Math.atan2(y-480/2,x))+90; }else{ mAngle=-Math.toDegrees(Math.atan2(y-480/2,320-x))+90; } Log.w("angle","mangle:"+mAngle); } break; caseMotionEvent.ACTION_UP: if(mTouchTimes>TOUCH_TIMES){ }else{ } mTouchTimes=0; break; default: break; } returntrue; } }; mView.setOnTouchListener(mTouchListener);
通过此文,希望能帮助开发Android应用使用触摸事件的朋友,谢谢大家对本站的支持!