Android View的体系

1.Android View简介:

View是Android所有控件的基类,同时ViewGroup也是继承自View,看下面这张图我们就会有一个直观的了解:
Android View的体系
Android应用的所有UI组件都是继承了View类,View组件非常类似于Swing编程的JPanel,它表示一个空白的矩形区域。View类还有一个很重要的子类:ViewGroup,但是ViewGroup通常作为其他组件的容器使用。Android的所有UI组件都是建立在View、ViewGroup基础之上的,Android采用了“组合器”模式来设计View和ViewGroup:ViewGroup是View的子类,因此ViewGroup也可以被当做View使用。对于一个Android应用的图形用户界面来说,ViewGroup作为容器来盛装其他组件,而ViewGroup里除了可以包含普通View组件之外,还可以再次包含ViewGroup组件。

简单的说View是所有控件的“祖宗”,无论TextView、Button、Linearlayout,还是ListView、RecycleView,他们的基类都是View,多个View形成了ViewGroup,ViewGroup本身也是View,比如,TextView是一个View,LinearLayout是一个ViewGroup,ViewGroup中又可以添加许多View。

知道了View的层级关系有助于对View的理解,从上图可以发现我们常用的这些控件都是继承于View,如果我们更好的掌握了View的知识体系,那么我们在界面编程时则会更加的得心应手。

2.Android坐标系

View坐标是相对于View的父容器来讲的,View看作一个矩形,则View的左上角坐标为(left,top),Vew的右下角的坐标为(right,top),View如果发生改变,这四个值并不会发生改变,改变的是View的偏移量。

Android View的体系
由坐标系则可以看出View的宽度为right - left 即getLeft() - getRight();View的高度为bottom - top 即getBoottom() - getTop();

2.1静态坐标系

***left = getLeft()***:View自身左侧到父View左侧的距离
***top = getTop()***:View自身顶部到父View顶部的距离
***right = getRight()***:View自身右侧到父View左侧的距离
***botton = getBotton()***:View自身底部到父View顶部的距离
***getTranslationX()***:View左上角相对父View的X轴偏移量
***getTranslationY()***:View左上角相对父View的Y轴偏移量
***getX()***:其值为:getLeft()+getTranslationX(),当setTranslationX 时,getLeft()不会变,getX会变
***getY()***:其值为:getTop()+getTranslationY(),当setTranslationY 时,getTop()不会变,getY会变

MationEvent 触摸事件坐标:
getX():当前触摸点距离当前 View 自身左边的距离
getY():当前触摸点距离当前 View 自身顶部的距离
getRawX():当前触摸点距离屏幕左边的距离(Android绝对坐标系)
getRawY():当前触摸点距离屏幕顶部的距离(Android绝对坐标系)

View获取自身宽高

1.getHeight():获取View自身高度
2.getWidth():获取View自身宽度

View自身坐标

通过如下方法可以获得View到其父控件(ViewGroup)的距离:
1.getTop():获取View自身顶边到其父布局顶边的距离。
2.getLeft():获取View自身左边到其父布局左边的距离。
3.getRight():获取View自身右边到其父布局左边的距离。
4.getBottom():获取View自身底边到其父布局顶边的距离。

3.MotionEvent和TouchSlop

3.1MotionEvent

当手指触摸屏幕是(View或ViewGroup派生的控件),将产生Touch事件Touch事件的相关细节(触摸发生的位置、事件及怎么的触摸)被封装成MotionEvent对象。

在手指触摸屏幕后所产生的一系列Touch事件中,事件类型如下:
MotionEvent.ACTION_DOWN(手指刚接触屏幕)
MotionEvent.ACTION_UP(手指从屏幕上松开的一瞬间)
MotionEvent.ACTION_MOVE(手指在屏幕上移动)
MotionEvent.ACTION_CANCEL(动作取消(非人为))

正常情况下,一次手指触摸屏幕的行为会触发一系列点击事件,一般会有两种情况:
(1)点击屏幕后离开松开,事件序列为 DOWN -> UP;
(2)点击屏幕滑动一会再松开,事件序列为 DOWN -> MOVE ->….-> MOVE -> UP;
在上述典型的三种Tocuh事件,我们可以通过TotionEvent对象得到点击事件发生的x和y的坐标。为此,系统提供了两组方法:getX/getY和getRawX/getRawY。区别如下:
(1)getX/getY:返回的是相对于当前View左上角的 x 和 y 坐标
(2)getRawX/getRawY : 返回的是相对于手机屏幕左上角的 x 和 y 坐标

3.2TouchSlop

TouchSlop是处理触摸事件中的一个常量,被系统认为滑动和点击事件的临界点。理 解这个touchSlop是一个滑动距离值的常量,也就是说当我们手触摸在屏幕上滑动时,如果滑动距离没有超过touchSlop值的话 ,android系统本身是不会认为我们在屏幕上做了手势滑动,因此只有当我们在屏幕上的滑动距离超过touchSlop值时,android系统本身才 会认为我们做了滑动操作并去响应触摸事件,不过要注意的是不同的设备,touchSlop的值可能是不同的,一切以函数获取为准。其次它在各自手机上的默认值是不相同的。

通过:ViewConfiguration.get(getContext()).getScaledTouchSlop() 获取系统的滑动常量来,判断此时是否属于滑动事件
其中ViewConfiguration这个类主要定义了UI中所使用到的标准常量,像超时、尺寸、距离。
在处理滑动事件时,其实可以利用这个值来过滤掉一些没必要的动作,比如当两次滑动距离小于这个值时,我们就可以认为滑动没发生,从而更好的优化用户体验。

4.手势(Gesture)

所谓手势,其实是指用户手指在触摸屏上的连续碰撞行为,比如在屏幕上从左至右划出的一个动作,就是手势;在比如在屏幕上画出一个圆圈也是手势。手势这种连续的碰撞会形成某个方向上的移动趋势,也会形成一个不规则的几何图形。Android 对于这两种手势行为都提供了支持。
对于第一种手势行为,Android 提供了手势检测,并为手势检测提供了相应的监听器。
对于第二种手势行为,Android 允许开发者添加手势,并提供相应的API识别用户手势。

4.1VelocityTracker

VelocityTracker是个速度跟踪类,用于跟踪手指滑动的速度,包括x轴方向和y轴方向的速度。如快速滑动或者其他手势操作。当我们准备开始跟踪滑动速率时可以使用obtain()方法来获取一个 VelocityTracker的实例,然后在onTouchEvent回调函数中,使用addMovement(MotionEvent)函数将当前的 移动事件传递给VelocityTracker对象。当我们决定计算当前触摸点的速率时可以调用computeCurrentVelocity(int units)函数来计算当前的速度,使用getXVelocity() 、getYVelocity()函数来获得当前X轴和Y轴的速度。

注意事项:
(1)获取速度之前必须先计算速度,即 getXVelocity 和 getYVelocity这两个方法的前面必须要调用 computeCurrentVelocity 方法;
(2)这里的速度是指一段时间内手指所滑动过的像素。

4.2GestureDetector

Android 为手势提供了一个 GestureDetector 类,GestureDetector 实例代表了一个手势检测器,用于辅助检测用户的单击、滑动、长按、双击等行为。GestureDetector内部有3个Listener接口,用来回调不同类型的触摸事件。

4.2.1GestureDetector 这个类对外提供了3个接口和一个静态内部类

OnGestureListener:手势检测,主要有事件类型为:按下(Down)、快速滑动(Fling)、长按(LongPress)、滚动(Scroll)、触摸反馈(ShowPress)和单击抬起(SingleTapUp)。
OnDoubleTapListener:双击检测,有三个回调类型:双击(DoubleTap)、单击确认(SingleTapConfirmed)和双击事件回调(DoubleTapEvent)。
OnContextClickListener:这是Android6.0(23)才添加的,用于检测外部设备上的按钮是否按下,一般情况下可忽略。
SimpleOnGestureListener:这个是上述三个接口的空实现,一般情况下使用这个比较多,也比较方便。