目的:通過全面的分析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));