天天看點

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));