天天看点

Android 事件处理

目的:通过全面的分析android的鼠标和键盘事件。了解android中如何接收和处理键盘和鼠标事件,以及如何用代码来产生事件。

主要学习内容:

1. 接收并处理鼠标事件:按下、弹起、移动、双击、长按、滑动、滚动

2. 接收并处理按键事件:按下、弹起

3. 模拟鼠标/按键事件

1. android事件

现代的用户界面,都是以事件来驱动的来实现人机交换的,而android上的一套ui控件,无非就是派发鼠标和键盘事件,然后每个控件收到相应的事件之后,做相应的处理。如button控件,就只需要处理down、move、up这几个事件,down的时候重绘控件,move的时候一般也需要重绘控件,当up的时候,重绘控件,然后产生onclick事件。在android中通过实现onclicklistener接口的onclick方法来实现对button控件的处理。

对于触摸屏事件(鼠标事件)有按下有:按下、弹起、移动、双击、长按、滑动、滚动。按下、弹起、移动(down、move、up)是简单的触摸屏事件,而双击、长按、滑动、滚动需要根据运动的轨迹来做识别的。在android中有专门的类去识别,android.view.gesturedetector。

对于按键(keyevent),无非就是按下、弹起、长按等。

2. android事件处理

android手机的坐标系是以左上定点为原点坐标(0,0), 向右为x抽正方形,向下为y抽正方向。

2.1 简单触摸屏事件

在android中任何一个控件和activity都是间接或者直接继承于android.view.view。一个view对象可以处理测距、布局、绘制、焦点变换、滚动条,以及触屏区域自己表现的按键和手势。当我们重写view中的ontouchevent(motionevent)方法后,就可以处理简单的触摸屏事件。

代码如下:

view plaincopy to clipboardprint?

public boolean ontouchevent(motionevent event)   

    {   

        int events[] = {motionevent.action_down, motionevent.action_move,   

                motionevent.action_up, motionevent.action_move, motionevent.action_cancel, motionevent.action_outside,   

                motionevent.action_pointer_down,motionevent.action_pointer_up,   

                motionevent.edge_top,motionevent.edge_bottom,motionevent.edge_left,motionevent.edge_right};   

        string szevents[]={"action_down", "action_move",   

        "action_up", "action_move", "action_cancel", "action_outside",   

        "action_pointer_down","action_pointer_up",   

        "edge_top","edge_bottom","edge_left","edge_right"};   

        for(int i=0; i < events.length; i++)   

        {   

            if(events[i] == event.getaction())   

            {   

                if(oldevent != event.getaction())   

                {   

                    displayeventtype(szevents[i]);   

                    oldevent = event.getaction();   

                }   

                break;   

            }   

        }   

        return super.ontouchevent(event);   

    }  

public boolean ontouchevent(motionevent event)

 {

  int events[] = {motionevent.action_down, motionevent.action_move,

    motionevent.action_up, motionevent.action_move, motionevent.action_cancel, motionevent.action_outside,

    motionevent.action_pointer_down,motionevent.action_pointer_up,

    motionevent.edge_top,motionevent.edge_bottom,motionevent.edge_left,motionevent.edge_right};

  string szevents[]={"action_down", "action_move",

  "action_up", "action_move", "action_cancel", "action_outside",

  "action_pointer_down","action_pointer_up",

  "edge_top","edge_bottom","edge_left","edge_right"};

  for(int i=0; i < events.length; i++)

  {

   if(events[i] == event.getaction())

   {

    if(oldevent != event.getaction())

    {

     displayeventtype(szevents[i]);

     oldevent = event.getaction();

    }

    break;

   }

  }

  return super.ontouchevent(event);

 }

2.2手势识别

很多时候,一个好的用户界面能够吸引用户的眼球。现在我们经常看到一些好的界面都带有滑动、滚动等效果。但是触摸屏是不可能产生滚动、滑动的消息的,需要根据其运动的轨迹用算法去判断实现。在android系统中,android.view.gesturedetector来实现手势的识别,我们只需要实现其gesturedetector.ongesturelistener接口来侦听gesturedetector识别后的事件。我们需要在ontouchevent,gesturedetector的ontouchevent方法是进行轨迹识别。

import android.view.gesturedetector;   

import android.view.gesturedetector.ongesturelistener;   

public class testevent extends activity {   

    /** called when the activity is first created. */  

    textview    m_eventtype;   

    int oldevent = -1;   

    private gesturedetector gesturedetector= new gesturedetector(new ongesturelistener()   

        // 鼠标按下的时候,会产生ondown。由一个action_down产生。   

        public boolean ondown(motionevent event) {   

            displayeventtype("mouse down" + " " + event.getx() + "," + event.gety());   

            return false;   

        // 用户按下触摸屏、快速移动后松开,这个时候,你的手指运动是有加速度的。   

        // 由1个motionevent action_down,     

        // 多个action_move, 1个action_up触发     

        // e1:第1个action_down motionevent     

        // e2:最后一个action_move motionevent     

        // velocityx:x轴上的移动速度,像素/秒     

        // velocityy:y轴上的移动速度,像素/秒    

        public boolean onfling(motionevent e1, motionevent e2, float velocityx,     

                float velocityy) {   

            displayeventtype("onfling");   

        // 用户长按触摸屏,由多个motionevent action_down触发     

        public void onlongpress(motionevent event) {   

            displayeventtype("on long pressed");   

        // 滚动事件,当在触摸屏上迅速的移动,会产生onscroll。由action_move产生   

        // e1:第1个action_down motionevent   

        // distancex:距离上次产生onscroll事件后,x抽移动的距离   

        // distancey:距离上次产生onscroll事件后,y抽移动的距离   

        public boolean onscroll(motionevent e1, motionevent e2, float distancex,     

                float distancey) {   

            displayeventtype("onscroll" + " " + distancex + "," + distancey);   

        //点击了触摸屏,但是没有移动和弹起的动作。onshowpress和ondown的区别在于   

        //ondown是,一旦触摸屏按下,就马上产生ondown事件,但是onshowpress是ondown事件产生后,   

        //一段时间内,如果没有移动鼠标和弹起事件,就认为是onshowpress事件。   

        public void onshowpress(motionevent event) {   

            displayeventtype("pressed");   

        // 轻击触摸屏后,弹起。如果这个过程中产生了onlongpress、onscroll和onfling事件,就不会   

        // 产生onsingletapup事件。   

        public boolean onsingletapup(motionevent event) {   

            displayeventtype("tap up");   

    });   

    @override  

    public void oncreate(bundle savedinstancestate) {   

        super.oncreate(savedinstancestate);   

        setcontentview(r.layout.main);   

        m_eventtype = (textview)this.findviewbyid(r.id.eventtype);   

    }   

    public boolean ontouchevent(motionevent event)   

        if(gesturedetector.ontouchevent(event))   

            return true;   

        else  

}  

import android.view.gesturedetector;

import android.view.gesturedetector.ongesturelistener;

public class testevent extends activity {

    /** called when the activity is first created. */

 textview  m_eventtype;

 int oldevent = -1;

 private gesturedetector gesturedetector= new gesturedetector(new ongesturelistener()

    {

  // 鼠标按下的时候,会产生ondown。由一个action_down产生。

  public boolean ondown(motionevent event) {

   displayeventtype("mouse down" + " " + event.getx() + "," + event.gety());

   return false;

  // 用户按下触摸屏、快速移动后松开,这个时候,你的手指运动是有加速度的。

  // 由1个motionevent action_down,  

     // 多个action_move, 1个action_up触发  

     // e1:第1个action_down motionevent  

     // e2:最后一个action_move motionevent  

     // velocityx:x轴上的移动速度,像素/秒  

     // velocityy:y轴上的移动速度,像素/秒 

  public boolean onfling(motionevent e1, motionevent e2, float velocityx,  

             float velocityy) {

   displayeventtype("onfling");

  // 用户长按触摸屏,由多个motionevent action_down触发  

  public void onlongpress(motionevent event) {

   displayeventtype("on long pressed");

  // 滚动事件,当在触摸屏上迅速的移动,会产生onscroll。由action_move产生

     // e1:第1个action_down motionevent

     // distancex:距离上次产生onscroll事件后,x抽移动的距离

     // distancey:距离上次产生onscroll事件后,y抽移动的距离

  public boolean onscroll(motionevent e1, motionevent e2, float distancex,  

             float distancey) {

   displayeventtype("onscroll" + " " + distancex + "," + distancey);

  //点击了触摸屏,但是没有移动和弹起的动作。onshowpress和ondown的区别在于

  //ondown是,一旦触摸屏按下,就马上产生ondown事件,但是onshowpress是ondown事件产生后,

  //一段时间内,如果没有移动鼠标和弹起事件,就认为是onshowpress事件。

  public void onshowpress(motionevent event) {

   displayeventtype("pressed");

  // 轻击触摸屏后,弹起。如果这个过程中产生了onlongpress、onscroll和onfling事件,就不会

  // 产生onsingletapup事件。

  public boolean onsingletapup(motionevent event) {

   displayeventtype("tap up");

    });

    @override

    public void oncreate(bundle savedinstancestate) {

        super.oncreate(savedinstancestate);

        setcontentview(r.layout.main);

        m_eventtype = (textview)this.findviewbyid(r.id.eventtype);

    }

 @override

 public boolean ontouchevent(motionevent event)

  if(gesturedetector.ontouchevent(event))

   return true;

  else

}

2.3键盘事件

键盘事件比较简单,直接重写原来的方法就可以了。

public boolean onkeydown(int keycode, keyevent event)    

        switch(keycode)   

        case keyevent.keycode_home:   

            displayeventtype("home down");   

            break;   

        case keyevent.keycode_back:   

            displayeventtype("back down");   

        case keyevent.keycode_dpad_left:   

            displayeventtype("left down");   

        //return true;   

        return super.onkeydown(keycode, event);   

    public boolean onkeyup(int keycode, keyevent event)    

            displayeventtype("home up");   

            displayeventtype("back up");   

            displayeventtype("left up");   

        return super.onkeyup(keycode, event);   

public boolean onkeydown(int keycode, keyevent event) 

  switch(keycode)

  case keyevent.keycode_home:

   displayeventtype("home down");

   break;

  case keyevent.keycode_back:

   displayeventtype("back down");

  case keyevent.keycode_dpad_left:

   displayeventtype("left down");

  //return true;

  return super.onkeydown(keycode, event);

 public boolean onkeyup(int keycode, keyevent event) 

   displayeventtype("home up");

   displayeventtype("back up");

   displayeventtype("left up");

  return super.onkeyup(keycode, event);

instrumentation发送键盘鼠标事件:instrumentation提供了丰富的以send开头的函数接口来实现模拟键盘鼠标,如下所述:

sendcharactersync(int keycode)            //用于发送指定keycode的按键

sendkeydownupsync(int key)                //用于发送指定keycode的按键

sendpointersync(motionevent event)     //用于模拟touch

sendstringsync(string text)                   //用于发送字符串

    instrumentation inst=new instrumentation();

                     inst.sendpointersync(motionevent.obtain(systemclock.uptimemillis(),systemclock.uptimemillis(), motionevent.action_down, 10, 10, 0));

                     inst.sendpointersync(motionevent.obtain(systemclock.uptimemillis(),systemclock.uptimemillis(), motionevent.action_up, 10, 10, 0));