Android View
Android View
1、View基础
1.1、什么是View
- View的位置主要由它的四个顶点来决定,分别对应于View的四个属性:top、left、right、bottom。
- 从Android3.0开始,View增加了额外的几个参数:x、y、translationX和translationY,其中x和y是View左上角的坐标,而translationX和translationY是View左上角相对于父容器的偏移量。
- View在平移的过程中,top和left表示的是原始左上角的位置信息,其值并不会发生改变,此时发生改变的是x、y、translationX和translationY这四个参数。
- MotionEvent:
ACTION_DOWN——手指刚接触屏幕;
ACTION_MOVE——手指在屏幕上移动;
ACTION_UP——手机从屏幕上松开的一瞬间。
同时通过MotionEvent对象我们可以得到点击事件发生的x和y坐标。为此,系统提供了两组方法:getX/getY和getRawX/getRawY。它们的区别其实很简单,getX/getY返回的是相对于当前View左上角的x和y坐标,而getRawX/getRawY返回的是相对于手机屏幕左上角的x和y坐标。
- TouchSIop:系统所能识别出的被认为是滑动的最小距离。通过如下方式即可获取这个常量:ViewConfiguration.get(getContext()).getScaledTouchSlop()。
- VeIocityTracker:速度追踪,用于追踪手指在滑动过程中的速度,包括水平和竖直方向的速度。它的使用过程很简单,首先,在View的onTouchEvent方法中追踪当前单击事件的速度
- GestureDetector:手势检测,用于辅助检测用户的单击、滑动、长按、双击等行为。
- ScroIIer:弹性滑动对象,用于实现View的弹性滑动。
2、View的滑动
通过三种方式可以实现View的滑动:第一种是通过View本身提供的scrollTo/scrollBy方法来实现滑动;第二种是通过动画给View施加平移效果来实现滑动;第三种是通过改变View的LayoutParams使得View重新布局从而实现滑动。
- 使用scrollTo/scrollBy。 它只能滑动View的内容,并不能滑动View本身。
- 使用动画
- 改变布局参数
3、View的时间分发机制
点击事件的分发过程由三个很重要的方法来共同完成:
- public boolean dispatchTouchEvent(MotionEvent ev) 如果事件能够传递给当前View,那么此方法一定会被调用,返回结果受当前View的onTouchEvent和下级View的dispatchTouchEvent方法的影响,表示是否消耗当前事件。
- public boolean onInterceptTouchEvent(MotionEventevent) 在上述方法内部调用,用来判断是否拦截某个事件,如果当前View拦截了某个事件,那么在同一个事件序列当中,此方法不会被再次调用,返回结果表示是否拦截当前事件。
- public boolean onTouchEvent(MotionEvent event) 在dispatchTouchEvent方法中调用,用来处理点击事件,返回结果表示是否消耗当前事件,如果不消耗,则在同一个事件序列中,当前View无法再次接收到事件。

4、滑动冲突解决方案
- 外部拦截法:重写父view的onteceptTouchEvent,由父类决定是否下发
- 内部拦截法:重写父viewonteceptTouchEvent,除了DOWN事件不拦截,其他一律拦截,重写子view的dispatchTouchEvent,通过修改disallowTouchEvent的标志位来决定父view是否消费事件。
5、viewRoot和DecorView
ViewRoot对应于ViewRootImpl类,它是连接WindowManager和DecorView的纽带,View的三大流程均是通过ViewRoot来完成的。在ActivityThread中,当Activity对象被创建完毕后,会将DecorView添加到Window中,同时会创建ViewRootImpl对象,并将ViewRootImpl对象和DecorView建立关联。
View的绘制流程是从ViewRoot的performTraversals方法开始的,

6、MeasureSpec
- MeasureSpec代表一个32位int值,高2位代表SpecMode,低30位代表SpecSize, SpecMode是指测量模式,而SpecSize是指在某种测量模式下的规格大小
- SpecMode有三类,每一类都表示特殊的含义。 (1) UNSPECIFIED 父容器不对View有任何限制,要多大给多大,这种情况一般用于系统内部,表示一种测量的状态。 (2)EXACTLY 父容器已经检测出View所需要的精确大小,这个时候View的最终大小就是SpecSize所指定的值。它对应于LayoutParams中的match_parent和具体的数值这两种模式 (3)AT_MOST 父容器指定了一个可用大小即SpecSize, View的大小不能大于这个值,具体是什么值要看不同View的具体实现。它对应于LayoutParams中的wrap_content
拍
7、获取view的宽高
- Activity/View#onWindowFocusChanged。 onWindowFocusChanged这个方法的含义是:View已经初始化完毕了,宽/高已经准备好了,这个时候去获取宽/高是没问题的。通过post可以将一个runnable投递到消息队列的尾部,然后等待Looper调用此runnable的时候,View也已经初始化好了。典型代码如下:
- ViewTreeObserver。使用ViewTreeObserver的众多回调可以完成这个功能,比如使用OnGlobalLayoutListener这个接口