• 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方法是进行轨迹识别。

    代码如下:

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

  • 相关阅读:
    [Perl]Windows 系统 Unicode 文件名操作(新建、重命名、枚举、复制)全攻略
    [Perl]Can't link/include C library 'ft2build.h', 'freetype', aborting.
    ompparticles.cpp:(.text+0x322): undefined reference to `omp_set_num_threads'
    undefined reference to `omp_get_max_threads'
    使用MinGW 编译 iconv 库
    phpBB论坛 代码 语法高亮 模块 Codebox Plus
    最新版Mac系统(10.14.4) && Xcode(10.2.1) 无法使用dwarfdump 解析闪退的问题
    Xcode 8 打包教程
    Xcode 8.0无法注释的问题
    我的github地址,里边有一些拍照功能,选择照片功能的实现,还有一些其它的开源项目
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4792774.html
Copyright © 2020-2023  润新知