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事件。
boolean ondoubletap(motionevent e)
解释:双击的第二下touch down时触发
boolean ondoubletapevent(motionevent e)
解释:双击的第二下touch down和up都会触发,可用e.getaction()区分。
boolean ondown(motionevent e)
解释:touch down时触发
boolean onfling(motionevent e1, motionevent e2, float velocityx,float velocityy)
解释:touch了滑动一点距离后,up时触发。
void onlongpress(motionevent e)
解释:touch了不移动一直touch down时触发
boolean onscroll(motionevent e1, motionevent e2, float distancex,float distancey)
解释:touch了滑动时触发。
void onshowpress(motionevent e)
解释:touch了还没有滑动时触发
(与ondown,onlongpress比较
ondown只要touch down一定立刻触发。
而touchdown后过一会没有滑动先触发onshowpress再是onlongpress。
所以touchdown后一直不滑动,ondown->onshowpress->onlongpress这个顺序触发。
)
boolean onsingletapconfirmed(motionevent e)
boolean onsingletapup(motionevent e)
解释:上面这两个函数都是在touchdown后又没有滑动(onscroll),又没有长按(onlongpress),然后touchup时触发。
点击一下非常快的(不滑动)touchup:
ondown->onsingletapup->onsingletapconfirmed
点击一下稍微慢点的(不滑动)touchup:
ondown->onshowpress->onsingletapup->onsingletapconfirmed
publicclassgestureactivityextendsactivityimplementsontouchlistener, ongesturelistener { gesturedetector detector; publicgestureactivity(){ detector = new gesturedetector(this); } publicvoidoncreate(bundlesavedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); textview tv = (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(view v,motionevent event) { returndetector.ontouchevent(event); } // 用户轻触触摸屏,由1个motioneventaction_down触发 publicbooleanondown(motioneventarg0) { log.i("mygesture","ondown"); toast.maketext(this, "ondown",toast.length_short).show(); returntrue; } publicvoidonshowpress(motionevent e) { log.i("mygesture","onshowpress"); toast.maketext(this, "onshowpress",toast.length_short).show(); } // 用户(轻触触摸屏后)松开,由一个1个motioneventaction_up触发 publicbooleanonsingletapup(motionevent e) { log.i("mygesture","onsingletapup"); toast.maketext(this, "onsingletapup",toast.length_short).show(); returntrue; } // 用户按下触摸屏、快速移动后松开,由1个motioneventaction_down, 多个action_move, 1个action_up触发 publicbooleanonfling(motionevente1, motionevent e2, float velocityx, float velocityy) { 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","fling left"); 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","fling right"); 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","fling down"); toast.maketext(this, "flingdown",toast.length_short).show(); } elseif(e1.gety()-e2.gety()>fling_min_distance && math.abs(velocityy)>fling_min_velocity) { // fling up log.i("mygesture","fling up"); toast.maketext(this, "flingup",toast.length_short).show(); } returnfalse; } // 用户按下触摸屏,并拖动,由1个motioneventaction_down, 多个action_move触发 publicbooleanonscroll(motionevente1, motionevent e2, float distancex, float distancey) { log.i("mygesture","onscroll"); toast.maketext(this, "onscroll",toast.length_long).show(); returntrue; } // 用户长按触摸屏,由多个motioneventaction_down触发 publicvoidonlongpress(motionevent e) { log.i("mygesture","onlongpress"); toast.maketext(this, "onlongpress",toast.length_long).show(); } }
2)在view的新建一个gesturedetector的对象。
构造函数里
gesturedetector = new gesturedetector(newhahagesturedetectorlistener());
然后在view的ontouchevent里以下这样用,就可以在刚才1)弄的事件里写自己的代码了。
@override public boolean ontouchevent(motionevent event) { gesturedetector.ontouchevent(event); } mtouchlistener = new ontouchlistener() { @override public boolean ontouch(view v, motionevent event) { // todo auto-generated method stub float x =event.getxprecision()*event.getx()+event.getx(); float y =event.getyprecision()*event.gety()+event.gety(); switch (event.getaction()) { case motionevent.action_down: break; case motionevent.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; case motionevent.action_up: if (mtouchtimes > touch_times) { } else { } mtouchtimes = 0; break; default: break; } return true; } }; mview.setontouchlistener(mtouchlistener);
通过此文,希望能帮助开发android应用使用触摸事件的朋友,谢谢大家对本站的支持!