欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android 的触摸事件详解及示例代码

程序员文章站 2024-03-06 17:43:50
由于触摸(touch)而触发的事件 android的事件:onclick, onscroll,onfling等等,都是由许多个touch组成的。其中touch的第一个状态...

由于触摸(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应用使用触摸事件的朋友,谢谢大家对本站的支持!