美文网首页
Android View的事件体系(一)基础知识

Android View的事件体系(一)基础知识

作者: 怡红快绿 | 来源:发表于2019-03-21 15:11 被阅读0次

一、什么是View

在开始深入了解View的事件体系之前,我们必须要了解到底什么是View。View是Android中所有控件的基类,TextView、Button、LinearLayout等控件都继承自View,这些View既可以是一个独立的控件,也可以是一个可以包含多个子View的控件组(ViewGroup),而且View与View之间是可以有嵌套关系的。例如比较常见的ViewGroup控件,它本身既是一个View,又可以包含多个子View。明白View的这种层级关系有助于理解View的工作机制。

接下来几节我们分析一些View中比较常用的基础概念。

二、View的位置参数

View的位置由它的四个顶点共同决定,分别对应View的四个属性:

  • top 左上角纵坐标
  • left 左上角横坐标
  • right 右下角横坐标
  • bottom 右下角纵坐标

也就是说,View的左上角坐标为(left,top),右下角坐标为(right,bottom)。如果想获取这些属性值,只需要调用 getTop()/getLeft()/getRight()/getBottom() 即可。
需要注意的是,这些坐标都是相对View的父容器来说的,是相对坐标。

坐标图

如图所示,我们可以很容易计算出:

width = right - left
height = bottom - top

Android3.0开始,增加了x、y、translationX和translationY,这几个参数也是相对父容器的坐标。(x、y)是View的左上角的坐标;translationX和translationY是View的左上角相对于父容器的偏移量,默认都为0。

这些参数的换算关系如下:

x = left + translationX
y = right + translationY

需要注意的是,View在平移过程中,发生变化的是x、y、translationX和translationY这四个参数,top和left表示的是左上角的原始坐标,其值是不会发生变化的。

三、MotionEvent和TouchSlop

MotionEvent

手指接触屏幕后会产生一系列事件,典型的事件类型

  • ACTION_DOWN 手指刚接触屏幕
  • ACTION_UP 手指从屏幕上拿开
  • ACTION_MOVE 手指在屏幕上移动

点击屏幕后直接松开,事件序列为ACTION_DOWN ->ACTION_UP
点击屏幕滑动一会再松开,事件序列为ACTION_DOWN -> ACTION_MOVE …… ACTION_MOVE -> ACTION_UP

除了以上提到的内容,我们还可以通过MotionEvent对象获取到点击事件的x、y坐标。系统提供了两组方法:

  • getX()/getY() 相对于当前View的左上角坐标
  • getRawX()/getRawY() 相对于手机屏幕左上角坐标

TouchSlop

TouchSlop是系统能识别出的被认为是滑动的最小距离,如果滑动的距离小于这个值,那么系统就不认为你是在进行滑动操作。这个值是一个常量,与设备有关,我们通常可以使用这个常量过滤一些我们认为没有意义的操作。这个常量的获取方式:ViewConfiguration.get(getContent()).getScaledTouchSlop() 。

四、VelocityTracker、GestureDetector和Scroller

VelocityTracker

速度追踪,用于追踪手指在屏幕上滑动的速度,包括水平速度和竖直速度。使用方法很简单:

  1. VelocityTracker.obtain()获取VelocityTracker 实例;
  2. velocityTracker.addMovement(event)把当前事件的event添加到velocityTracker里;
  3. 调用velocityTracker.computeCurrentVelocity(int units)设置速度的计算时间然后开始计算速度
  4. 最后就可以使用velocityTracker.getXVelocity()获取速度。

这里的速度指的是一段时间内手指滑过的像素数。速度的计算公式很简单:

速度计算公式

根据Android系统的坐标系和上面的公式我们可以知道,速度也可以是负值。下面是VelocityTracker 使用示例:

        VelocityTracker velocityTracker = VelocityTracker.obtain();
        velocityTracker.addMovement(event);
        //有一点要注意,必须要先执行计算速度的方法computeCurrentVelocity,才能获取到速度
        velocityTracker.computeCurrentVelocity(1000);
        //获取不同方向的速度
        float xVelocity = velocityTracker.getXVelocity();
        float yVelocity = velocityTracker.getYVelocity();

最后,当我们不再使用它的时候,我们需要调用它的clear或者recycle来重置并回收内存。

        if (velocityTracker != null) {
            velocityTracker.clear();
            //or
            velocityTracker.recycle();
        }

GestureDetector

GestureDetector被翻译为手势检测器,它的主要作用是辅助检测用户的单击、双击、长按、滑动等一系列行为,它的使用过程也比较简单。

1. 首先需要创建一个GestureDetector对象,并且实现OnGestureListener接口中的一系列方法
gestureDetector = new GestureDetector(getApplicationContext(), new GestureDetector.OnGestureListener() {
    @Override
    public boolean onDown(MotionEvent e) {
        return false;
    }

    @Override
    public void onShowPress(MotionEvent e) {

    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        return false;
    }

    @Override
    public void onLongPress(MotionEvent e) {

    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        return false;
    }
});

我们也可以选择性地实现OnDoubleTapListener接口来监听双击行为

gestureDetector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() {
    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onDoubleTap(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onDoubleTapEvent(MotionEvent e) {
        return false;
    }
});
2. 接着我们就可以使用gestureDetector对象接管目标View的onTouchEvent方法
@Override
public boolean onTouchEvent(MotionEvent event) {
    return gestureDetector.onTouchEvent(event);
}

至此,手势检测已经准备就绪了,接下来的工作就是根据需要重写OnGestureListener和OnDoubleTapListener接口内的方法,所以我们必须要了解各个方法的含义。

接口方法说明(1)
接口方法说明(2)

如果只是监听滑动相关的事件,我们可以自己在onTouchEvent中实现,如果要监听双击这种行为,使用GestureDetector会比较合适。   ——《Android开发艺术探索》作者给读者的建议

Scroller

Scroller是弹性滑动对象,用于完成View的弹性滑动。一般情况,我们可以直接使用View的scrollTo和scrollBy方法来进行滑动,但是这种滑动是瞬间完成的,没有过渡效果。但是Scroller不同,它在实现滑动的时候是有过渡效果的,所以用它来实现滑动能提升用户体验。Scroller本身无法让View弹性滑动,需要配合View的computeScroll方法一起使用才能完成这个功能。

下一篇:Android View的事件体系(二)View的滑动


参考

《Android开发艺术探索》

相关文章

网友评论

      本文标题:Android View的事件体系(一)基础知识

      本文链接:https://www.haomeiwen.com/subject/exorpqtx.html