Android 系统中的所有 UI 类都是建立在 View 和 ViewGroup 两个类的基础之上的,
所有 View 的子类称为 Widget,
所有 ViewGroup 的子类称为 Layout。
Activity 是 Android 应用程序与用户交互的接口,每一个屏幕视图都对应一个 Activity。View和ViewGroup的区别 可以从两方面来说:
一.事件分发方面的区别;
Touch事件分发中只有两个主角:ViewGroup和View。
ViewGroup包含onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent三个相关事件。
View包含dispatchTouchEvent、onTouchEvent两个相关事件。其中ViewGroup又继承于View。
1当某个子View的dispatchTouchEvent()返回true时,会中止Down事件的分发,同时在ViewGroup中记录该子View。接下来的Move和Up事件将由该子View直接进行处理。
2.当ViewGroup中所有子View都不捕获Down事件时,将触发ViewGroup自身的onTouch();触发的方式是调用super.dispatchTouchEvent函数,即父类View的dispatchTouchEvent方法。在所有子View都不处理的情况下,触发Acitivity的onTouchEvent方法。
3.onInterceptTouchEvent有两个作用:拦截Down事件的分发。中止Up和Move事件向目标View传递,使得目标View所在的ViewGroup捕获Up和Move事件。
4.子View可以调getParent().requestDisallowInterceptTouchEvent(),请求父ViewGroup不拦截事件。
二.UI绘制方面的区别;
ViewGroup和View组成了一个树状结构,根节点为Activity内部包含的一个ViwGroup。
UI绘制主要有五个方法:onDraw(),onLayout(),onMeasure(),dispatchDraw(),drawChild()
1.ViewGroup包含这五个方法,而View只包含onDraw(),onLayout(),onMeasure()三个方法,不包含dispatchDraw(),drawChild()。
2.绘制流程:onMeasure(测量)——》onLayout(布局)——》onDraw(绘制)。
3.绘制按照视图树的顺序执行,视图绘制时会先绘制子控件。如果视图的背景可见,视图会在调用onDraw()之前调用drawBackGround()绘制背景。强制重绘,可以使用invalidate();
4.如果发生视图的尺寸变化,则该视图会调用requestLayou(),向父控件请求再次布局。如果发生视图的外观变化,则该视图会调用invalidate(),强制重绘。如果requestLayout()或invalidate()有一个被调用,框架会对视图树进行相关的测量、布局和绘制。
注意:视图树是单线程操作,直接调用其它视图的方法必须要在UI线程里。跨线程的操作必须使用Handler。
5.onLayout():对于View来说,onLayout()只是一个空实现;而对于ViewGroup来说,onLayout()使用了关键字abstract的修饰,要求其子类必须重载该方法,目的就是安排其children在父视图的具体位置。
6.draw过程:drawBackground()绘制背景——》onDraw()对View的内容进行绘制——》dispatchDraw()对当前View的所有子View进行绘制——》onDrawScrollBars()对View的滚动条进行绘制。
方法说明:
1.onDraw(Canvas canvas):UI绘制最重要的方法,用于UI重绘。这个方法是所有View、ViewGroup及其派生类都具有的方法。自定义控件时,可以重载该方法,并在内容基于canvas绘制自定义的图形、图像效果。
2.onLayout(boolean changed, int left, int top, int right, int bottom):布局发生变化时调用此方法。这个方法是所有View、ViewGroup及其派生类都具有的方法。自定义控件时,可以重载该方法,在布局发生改变时实现特效等定制处理。
3.onMeasure(int widthMeasureSpec, int heightMeasureSpec):用于计算自己及所有子对象的大小。这个方法是所有View、ViewGroup及其派生类都具有的方法。自定义控件时,可以重载该方法,重新计算所有对象的大小。 MeasureSpec包含了测量的模式和测量的大小,通过MeasureSpec.getMode()获取测量模式,通过MeasureSpec.getSize()获取测量大小。mode共有三种情况: 分别为MeasureSpec.UNSPECIFIED( View想多大就多大), MeasureSpec.EXACTLY(默认模式,精确值模式:将layout_width或layout_height属性指定为具体数值或者match_parent。), MeasureSpec.AT_MOST( 最大值模式:将layout_width或layout_height指定为wrap_content。)。
4.dispatchDraw(Canvas canvas):ViewGroup及其派生类具有的方法,主要用于控制子View的绘制分发。自定义控件时,重载该方法可以改变子View的绘制,进而实现一些复杂的视效。
5.drawChild(Canvas canvas, View child, long drawingTime):ViewGroup及其派生类具有的方法,用于直接绘制具体的子View。自定义控件时,重载该方法可以直接绘制具体的子View。