zoukankan      html  css  js  c++  java
  • Android开发——用户在屏幕上的手势识别

    0. 前言  

    转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52462493

    Android开发中,我们常常需要获取用户的手势操作事件,从而回调相应的方法完成我们的逻辑业务,在讲手势识别之前,我们有必要了解一下View相关的位置属性。

     

    1.  View位置属性

    View是一种界面上控件的一种抽象,代表了一个控件。View有很多位置属性。


    如图所示,我们的View位置主要由4个定点决定。四个属性分别为left(1)top(2)right(3)bottom(4)

    数字为图上标出的距离。显然这四个属性是相对于父容器来定的,均可以通过get()方法获取。

    因此很容易得出View本身的宽高:

    width = getRight() - getLeft();
    height = getBottom() – getTop();
    

    需要注意的是,View在平移时,上述四个属性值是不会变的

    那么当View平移时,我们用什么属性来描述View相当于屏幕的位置变化?

    Android3.0开始,View新加了几个位置参数,分别为xytranslationXtranslationY。而这四个值是会改变的。

    前两者表示相对于父容器View左上角的坐标。后两者表示View左上角相对于父容器的偏移量,默认为0。


    2.   View的触摸事件

    当用户触摸屏幕时,可能发生按下(ACTION_DOWN),移动(ACTION_MOVE)以及抬起(ACTION_UP)三种事件。

    下面介绍一些重用的关于触摸事件的数据获取。

     

    2.1   获取事件发生位置

    我们可以通过通过getX/Y(相对于当前View左上角的坐标)getRawX/Y(相对于屏幕左上角的坐标)获取按下或抬起事件发生的位置。

     

    2.2   滑动

    对于滑动,这里有一个最小滑动距离的概念。小于该值系统不会认为这是滑动事件。

    只要有滑动,必然有滑动速度的概念。我们可以使用VelocityTracker测量滑动速度。

    //最小滑动距离
    ViewConfiguration.get(getContext()).getScaledTouchSlop();
    //获取滑动速度
    //在onTouchEvent中使用VelocityTracker
    VelocityTracker vt = VelocityTracker.obtain();
    vt.addMovement(event);
    //速度为100ms内滑动过的像素值,和我们理解的每秒滑动像素值的速度概念不同
    //同样的滑动速度,指定时间不一样,速度也不同,另外速度可为负
    vt.computeCurrentVelocity(100);
    int Vx = (int)vt.getXVelocity();
    int Vy = (int)vt.getYVelocity();
    //资源回收
    vt.clear();
    vt.recycle();


    2.3   手势检测

    在实际开发中,我们完全可以在onTouchEvent()中实现监听点击、抬起、滑动等行为。Android SDK给我们提供了GestureDetector,通过这个类的onTouchEvent(event)方法我们可以识别更多的手势,比如双击事件等等。

    GestureDetector的使用示例:

    /*
    *@author SEU_Calvin
    *@date 2010/09/10
    */
    private GestureDetector mGestureDetector = new GestureDetector(this, new MyGestureListener());
    //长按后可以拖动View
    mGestureDetector.setIsLongpressEnabled(false);
     @Override
    public boolean onTouchEvent(MotionEvent event) {
        //接管onTouchEvent方法
        return mGestureDetector.onTouchEvent(event);
    }
    
    class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
            @Override
            public boolean onDown(MotionEvent ev) {
                Log.d("onDown", ev.toString());
                return true;
            }
            //如果手指向左滑,左上角横坐标已经为负了,但是onScroll方法的distanceX为正的,同理右滑distanceX为负,Y轴也一样是反的
            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                Log.d("onScroll", e1.toString());
                return true;
            }
    
            @Override
            public void onLongPress(MotionEvent ev) {
                Log.d("onLongPress", ev.toString());
            }
    
            @Override
            public boolean onSingleTapUp(MotionEvent ev) {
                Log.d("onSingleTapUp", ev.toString());
                return true;
            }
    
            @Override
            public void onShowPress(MotionEvent ev) {
                Log.d("onShowPress ", ev.toString());
            }
    
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                  Log.d("onFling e1 ",e1.toString());
                  Log.d("onFling e2 ",e2.toString());
    
                  return true;
            }
    
            @Override
            public boolean onDoubleTap(MotionEvent e) {
                Log.d("onDoubleTap",e.toString());
                return super.onDoubleTap(e);
            }
    
            @Override
            public boolean onSingleTapConfirmed(MotionEvent e) {
                Log.d("onSingleTapConfirmed",e.toString());
                return super.onSingleTapConfirmed(e);
            }
    }
    

    上例中的SimpleOnGestureListenerGestureDetector提供给我们的一个更方便的响应不同手势的类,这个类实现了OnGestureListenerOnDoubleTapListener两个接口。该类是static class,也就是说它实际上是一个外部类,因此我们可以在外部继承这个类,重写里面的手势处理方法

     

    在看输出结果之前,先对实例中的回调方法进行总结:



    表格上已经把各个回调方法解释的很清楚了,这里需要介绍一下为什么双击时不会触发onSingleTapConfirmed,在第一次单击按下时,会给Hanlder发送了一个延时300ms的消息,如果300ms里,发生了第二次单击事件,那就认为是双击事件,并移除之前发送的延时消息。否则判定为触发SingleTapConfirmed


    上例的输出结果(可以自行结合上表进行分析):

    1)单次点击:


    2)长按:


    3)双击:


    4)滑动:


    5)快速滑动:



    滑动和快速滑动的结果来看,GestureDetector都没有“回应”抬起事件的回调。

    如果业务逻辑需要我们去“回应”,我们自己在onTouchEvent()中做处理即可。

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        mGestureDetector.onTouchEvent(event);
        //GestureDetector处理滑动的同时,自己处理抬起UP事件
        switch(event.getAction()){
        case MotionEvent.ACTION_UP:
        //UP事件处理
        break;
        //...
        //其他处理
      }
    }

    至此关于识别用户在屏幕上的手势介绍完毕。

    转载请标明出处:http://blog.csdn.net/seu_calvin/article/details/52462493


  • 相关阅读:
    中共中央办公厅的机构设置(局、室)
    清理winsxs文件夹(系统更新文件)的第三方工具
    通用的MIME类型:application/octet-stream
    “IIS7.5无法写入配置文件web.config”的解决方案
    刷新组策略的命令
    windows网络和共享中心“查看基本网络信息并设置连接”为“未知”的解决方案
    使 windows 无需输入开机密码自动进入系统
    windows server 2008 R2 的 FTP 防火墙的正确配置方法
    搜狗浏览器不能使用拖拽搜索的解决方案
    无法启动 Diagnostic Policy Service(服务错误 1079)的解决方案
  • 原文地址:https://www.cnblogs.com/qitian1/p/6461521.html
Copyright © 2011-2022 走看看