Android View原理浅析——View的事件体系

Android View原理浅析——View的事件体系

View是什么

首先我们需要理解什么是View。View是安卓中所有控件的基类,无论是简单的TextView、Button,还是复杂的LinearLayout、ListView,它们的共同基类都是View,ViewGroup其实也是继承了View。Button是一个View,而LinearLayout是View的同时也是ViewGroup,ViewGroup的内部可以有子View,而子View同样可以是ViewGroup,以此类推。

View的位置参数

View的位置由它的四个顶点来决定,分别对应了View的四个属性——top、left、right、bottom。需要注意的是,这些坐标都是相对于View的父容器而说的,是一种相对坐标。View的坐标和父容器的关系如图。在Android中,x、y轴的正方向分包为右、下。

img

很容易得出,View宽高和坐标关系如下:

width = right - left

height = bottom - top

通过View的getLeft()、getRight()…方法可以得到这四个参数。

从Android 3.0开始,View增加了几个额外的参数:x.、y、translateX、translateY。x、y是View左上角的坐标,而translateX,translateY则是View左上角相对于父容器的偏移量。这几个参数也是相对父容器的坐标,并且translateX、translateY的默认值为0。与前面的参数一样,View也为它们提供了get/set方法。

需要注意:View平移过程中,top、left表示的是原始左上角位置,并不会改变。此时发生改变的是x、y、translatX、translateY这四个参数。

MotionEvent和TouchSlop

MotionEvent

手指接触屏幕后产生的一系列事件中,典型的事件类型有一下几种:

  • ACTION_DOWN:手指刚刚接触屏幕
  • ACTION_MOVE:手指在屏幕上移动
  • ACTION_UP:手指从屏幕松开的一瞬间

正常情况,一次手指触碰屏幕的行为会发生一系列点击事件,比如如下情况:

  • 点击屏幕后松开,事件顺序:DOWN->UP
  • 点击屏幕滑动一会松开,事件顺序:DOWN->MOVE->…->MOVE->UP

上述的情况是典型的事件序列,同时通过MotionEvent对象我们可以得到发生点击事件的x,y坐标。为此,系统提供了两组方法 getX/getYgetRawX/getRawY。它们的区别:getX/getY返回的是相对于当前View左上角的x,y坐标。getRawX/getRawY返回的是相对于屏幕左上角的x,y。

TouchSlop

TouchSlop是系统能识别的被认为滑动的最小距离。如果滑动时距离小于这个常量,则系统不认为这是滑动。它的值在不同设备上可能不同,通过 ViewConfiguration.get(getContext()).getScaledTouchSlop() 即可获取这个常量。这个常量的可以帮助我们在处理滑动时做一些过滤。

在源码中可以找到这个常量的定义,它处于frameworks/base/core/res/res/values/config.xml文件中。

VelocityTracker、GestureDetector 和 Scroller

VelocityTracker

顾名思义,速度追踪,用于追踪手指在滑动时的速度,包括水平和竖直方向的速度。使用过程很简单,首先在View的onTouchEvent中追踪当前单击事件的速度:

VelocityTracker velocityTracker = VelocityTracker.obtain();
velocityTracker.addMovement(event);

接着,当我们想知道当前滑动速度,可以采用如下方式:

VelocityTracker.computeCurrentVelocity(1000);
int xVelocity = (int) velocityTracker.getXVelocity();
int yVelocity = (int) velocityTracker.getYVelocity();

有两点需要注意:

一、获取速度前必须先计算速度,即先调用computeCurrentVelocity()方法。

二、此处的速度是指一段时间内手指划过的像素数,当手指从右往左划时,速度为负值。

最后,不需要使用它时,调用clear及recycle方法即可重置并回收内存。

velocityTracker.clear();
velocityTracker.recycle();

GestureDetector

手势检测,用于辅助用户单击、滑动、长按、双击等行为。

使用GestureDetector,首先需要创建一个GestureDetector对象并实现OnGestureListener接口,根据需要还可以实现OnDoubleTapListenr从而监听双击事件。

GestureDetector mGestureDetector = new GestureDetector(this);
//解决长按屏幕无法拖动的情况
mGestureDetector.setIsLongpressEnabled(false);

接着接管View的onTouchEvent方法,在其中添加如下实现:

boolean consume = mGestureDetector.onTouchEvent(event);
return consume;

之后,我们可以有选择地实现 OnGestureListener和OnDoubleTapListener中的方法了,这两个接口的方法介绍如表:

方法名 描述 所属接口
onDown 手指触摸屏幕一瞬间,由一个ACTION_DOWN触发 OnGestureListener
onShowPress 手指轻轻触摸屏幕,未松开或拖动,由一个ACTION_DOWN触发(注意与onDown的区别,它强调的是没有松开或拖动的状态) OnGestureListener
onSingleTapUp 手指触摸后松开,伴随一个MotionEvent ACTION_UP而触发,是单击行为 OnGestureListener
onScroll 手指按下屏幕并拖动,由一个ACTION_DOWN,多个ACTION_MOVE触发,是拖动行为 OnGestureListener
onLongPress 用户长按 OnGestureListener
onFling 用户按下触摸屏,快速滑动后松开,由一个ACTION_DOWN,多个ACTION_MOVE和一个ACTION_UP触发,是快速滑动行为 OnGestureListener
onDoubleTap 双击,由两次连续的单击组成,不可能与onSingleTapConfirmed共存 OnDoubleTapListener
onSingleTapConfirmed 严格的单击行为(注意它与onSingleTapUp的区别,如果触发了onSingTapConfirmed,那么后面不可能再跟着一个单击行为,即只可能是双击,不可能是双击中的一次单击)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值