目的:通过全面的分析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方法是进行轨迹识别。

代码如下:

view plaincopy to clipboardprint?
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");   
            return false;   
        }   
        // 用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发     
        public void onLongPress(MotionEvent event) {   
            DisplayEventType("on long pressed");   
        }   
        // 滚动事件,当在触摸屏上迅速的移动,会产生onScroll。由ACTION_MOVE产生   
        // e1:第1个ACTION_DOWN MotionEvent   
        // e2:最后一个ACTION_MOVE MotionEvent     
        // distanceX:距离上次产生onScroll事件后,X抽移动的距离   
        // distanceY:距离上次产生onScroll事件后,Y抽移动的距离   
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,     
                float distanceY) {   
            DisplayEventType("onScroll" + " " + distanceX + "," + distanceY);   
            return false;   
        }   
        //点击了触摸屏,但是没有移动和弹起的动作。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");   
            return false;   
        }   
           
    });   
       
    @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  
            return false;   
    }   
       
}  
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");
   return false;
  }
  // 用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发  
  public void onLongPress(MotionEvent event) {
   DisplayEventType("on long pressed");
  }
  // 滚动事件,当在触摸屏上迅速的移动,会产生onScroll。由ACTION_MOVE产生
     // e1:第1个ACTION_DOWN MotionEvent
     // e2:最后一个ACTION_MOVE MotionEvent  
     // distanceX:距离上次产生onScroll事件后,X抽移动的距离
     // distanceY:距离上次产生onScroll事件后,Y抽移动的距离
  public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,  
             float distanceY) {
   DisplayEventType("onScroll" + " " + distanceX + "," + distanceY);
   return false;
  }
  //点击了触摸屏,但是没有移动和弹起的动作。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");
   return false;
  }
     
    });
 
    @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
   return false;
 }
    
}

2.3键盘事件

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

代码如下:

view plaincopy to clipboardprint?
public boolean onKeyDown(int keyCode, KeyEvent event)    
    {   
        switch(keyCode)   
        {   
        case KeyEvent.KEYCODE_HOME:   
            DisplayEventType("Home down");   
            break;   
        case KeyEvent.KEYCODE_BACK:   
            DisplayEventType("Back down");   
            break;   
        case KeyEvent.KEYCODE_DPAD_LEFT:   
            DisplayEventType("Left down");   
            break;   
        }   
        //return true;   
        return super.onKeyDown(keyCode, event);   
    }   
    @Override  
    public boolean onKeyUp(int keyCode, KeyEvent event)    
    {   
        switch(keyCode)   
        {   
        case KeyEvent.KEYCODE_HOME:   
            DisplayEventType("Home up");   
            break;   
        case KeyEvent.KEYCODE_BACK:   
            DisplayEventType("Back up");   
            break;   
        case KeyEvent.KEYCODE_DPAD_LEFT:   
            DisplayEventType("Left up");   
            break;   
        }   
        //return true;   
        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");
   break;
  case KeyEvent.KEYCODE_DPAD_LEFT:
   DisplayEventType("Left down");
   break;
  }
  //return true;
  return super.onKeyDown(keyCode, event);
 }
 @Override
 public boolean onKeyUp(int keyCode, KeyEvent event) 
 {
  switch(keyCode)
  {
  case KeyEvent.KEYCODE_HOME:
   DisplayEventType("Home up");
   break;
  case KeyEvent.KEYCODE_BACK:
   DisplayEventType("Back up");
   break;
  case KeyEvent.KEYCODE_DPAD_LEFT:
   DisplayEventType("Left up");
   break;
  }
  //return true;
  return super.onKeyUp(keyCode, event);
 }

3. 模拟鼠标/按键事件

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

Android 事件处理的更多相关文章

  1. Android零基础入门第33节:Android事件处理概述

    原文:Android零基础入门第33节:Android事件处理概述 通过对Android基本组件的学习,也有接触少部分Android的事件处理,比如按钮的点击事件.选框的状态切换事件. 一.Andro ...

  2. android事件处理之基于监听

    Android提供了了两种事件处理方式:基于回调和基于监听. 基于监听: 监听涉及事件源,事件,事件监听器.用注册监听器的方法将某个监听器注册到事件源上,就可以对发生在事件源上的时间进行监听. 最简单 ...

  3. Android事件处理机制

    包括监听和回调两种机制. 1. 基于监听的事件处理: 事件监听包含三类对象,事件源,事件,事件监听器.Android的事件处理机制是一种委派式(Delegation)事件处理方式:普通组件(事件源)将 ...

  4. Android事件处理

    含义:为用户动作提供响应就是事件处理. Android提供了强大的事件处理机制:基于监听的事件处理.基于回调的事件处理. 一.基于监听的事件处理 监听的处理模型主要涉及三类对象 >Event S ...

  5. Android事件处理--读书笔记

    2013-12-28 17:57:17 1. Android提供了两种方式的事件处理:基于回调和基于监听的事件处理: 1.1 对基于监听的事件处理而言,主要做法是为Android界面组件绑定特定的事件 ...

  6. Android事件处理概述

    不管是桌面应用还是手机应用程序,面对最多的就是用户,经常需要处理的就是用户的动作——也就是需要为用户动作提供响应,这种为用户动作提供响应的机制就是事件处理. Android提供了强大的事件处理机制,包 ...

  7. android事件处理概括

    什么是事件处理? 事件处理就是针对用户的一些特定操作,进行相对应的回馈.时间处理也是程序开发中的人机交互的一个非常重要的体现.事件处理中,事件源是事件的起始位. 一.事件处理三要素 事件源——事件—— ...

  8. Android事件处理的2种方式:监听器与回调

    android组件的事件处理有2种方式: 1.基于监听器的事件处理方式:先定义组件,然后为组件设定监听器. 详见http://blog.csdn.net/jediael_lu/article/deta ...

  9. Android——事件处理模型一(基于回调机制的事件处理)(转)

    Android平台的事件处理机制有两种,一种是基于回调机制的,一种是基于监听接口的,现介绍第一种:基于回调机制的事件处理.Android平台中,每个View都有自己的处理事件的回调方法,开发人员可以通 ...

随机推荐

  1. 【Eclipse】WebServiceExplorer

    1.点击以下按钮启动Eclipse Web Service Explorer 2.点击页面右上角的WSDL PAGE按钮 3.点击页面左上角WSDL MAIN-->输入WSDL地址-->选 ...

  2. sql执行疑问

    遇到一个奇怪的事情,学习执行计划的时候写了这么一个sql来看执行计划的执行顺序, SELECT COUNT(*) FROM SIC84 WHERE AAC001 IN (SELECT AAC001 F ...

  3. HDU 5025Saving Tang Monk BFS + 二进制枚举状态

    3A的题目,第一次TLE,是因为一次BFS起点到终点状态太多爆掉了时间. 第二次WA,是因为没有枚举蛇的状态. 解体思路: 因为蛇的数目是小于5只的,那就首先枚举是否杀死每只蛇即可. 然后多次BFS, ...

  4. NanShan即时通讯论——HTML5的优势与劣势

    原文:NanShan即时通讯论--HTML5的优势与劣势 NanShan即时通讯 学习html时才是XHTML 1.0,接着是 HTML4.01,再到HTML5,如今HTML5 開始吸引越来越多的人的 ...

  5. Python 第四篇:生成器、迭代器、装饰器、递归函数与正则表达式

    一:生成器:Generator,可以理解为是一种一个函数产生一个迭代器,而迭代器里面的数据是可以通过for循环获取的,那么这个函数就是一个生成器,即生成器是有函数生成的,创建生成器使用()表示,比如g ...

  6. JVM-如何判断一段数据是真正的数据,还是对象的引用

    JVM 判断一段数据到底是数据还是引用类型,首先要看JVM选择用什么方式.通常这个选择会影响到GC的实现. 一.保守式 如果JVM选择不记录任何这种类型的数据,那么它就无法区分内存里某个位置上的数据到 ...

  7. spring MVC 如何获取session并实现传值到前台

    后台获取session: @RequestMapping("/usrlogin") public ModelAndView usrlogin(@RequestParam Strin ...

  8. CCIE路由实验(5) -- BGP负载均衡

    enableconf tno ip do loenable pass ciscoline con 0logg syncexec-t 0 0exitline vty 0 4pass ciscologg ...

  9. Deamon Thread 讲解

    The daemon thread's life cycle is same with the life cycle of the application which starts this daem ...

  10. 百度2015校园招聘自然语言处理project师面试

    面了一个多小时,大致回想下 1. 介绍一下简历上的项目 这个讲了好长时间,由于我做的是生物信息,面试官听得不太明确. 2. 一个城市每对夫妇都要生到一个男孩才停止生育,问终于该城市的男女比例 1:1, ...