1.坐标系
View获取自身宽高
- getHeight():获取View自身高度
- getWidth():获取View自身宽度
View自身坐标
通过如下方法可以获得View到其父控件(ViewGroup)的距离:
- getTop():获取View自身顶边到其父布局顶边的距离
- getLeft():获取View自身左边到其父布局左边的距离
- getRight():获取View自身右边到其父布局左边的距离
- getBottom():获取View自身底边到其父布局顶边的距离
MotionEvent提供的方法
无论是View还是ViewGroup,最终的点击事件都会由onTouchEvent(MotionEvent event)方法来处理,MotionEvent也提供了各种获取焦点坐标的方法:
- getX():获取点击事件距离控件左边的距离,即视图坐标
- getY():获取点击事件距离控件顶边的距离,即视图坐标
- getRawX():获取点击事件距离整个屏幕左边距离,即绝对坐标
- getRawY():获取点击事件距离整个屏幕顶边的的距离,即绝对坐标
2.View测量模式
单一View测量过程
imageViewRootImpl调用performMeasure方法后该方法中的DecorView又调用了measure方法,而DecorView的本质其实是集成自FrameLayout,那么本质就是一个ViewGroup,但是在FrameLayout和ViewGroup的源码中都没发现measure方法, 这就用到刚才的知识点了,ViewGroup本身也是View的子类,我们就去View的源码中查看一下,果然,measure方法赫然其中,在measure方法中,View又调用了其自身的方法onMeasure,而起自身的onMeasure方法中又调用setMeasureDimension方法,该方法有两个参数,这两个参数分别代表要设置的宽和高,而这两个参数都是是通过getDefaultSize方法来计算的,而getDefaultSize方法中有一个参数是根据getSuggestedMinimumWidth或getSuggestedMinimumHeight获得的。
ViewGroup的测量过程
image通过遍历所有的子View进行子View的测量,然后将所有子View的尺寸进行合并,最终得到ViewGroup父视图的测量值。
MeasureSpec————测量规格
第一个功能自然是测量值了(Size),第二个功能是测量的模式(Mode),这两个参数通过二进制将其打包成一个int(32位)值来减少对内存的分配,其高2位(31,32位)存放的是测量模式,而低30位则存储的是其测量值。
- UNSPECIFIED模式:本质就是不限制模式,父视图不对子View进行任何约束,View想要多大要多大,想要多长要多长,这个在我们写自定义View中的时候非常少见,一般都是系统内部在设置ListView或者是ScrollView的时候才会用到。
- EXACTLY模式:该模式其实对应的场景就是match_parent或者是一个具体的数据(50dp或80px),父视图为子View指定一个确切的大小,无论子View的值设置多大,都不能超出父视图的范围。
- AT_MOST模式:这个模式对应的场景就是wrap_content,其内容就是父视图给子View设置一个最大尺寸,子View只要不超过这个尺寸即可。
3.view体系结构
- View 是Android UI 控件的基类,ViewGroup也是继承自View,Android中的控件分为两部分,直接继承自View的控件和继承ViewGroup的布局(控件的集合),使整个Android控件形成的界面呈现出一个树形结构
- 在每个 Activity 创建时,同时会创建一个 Window (抽象类),Window 的具体通过 PhotoWindow 类实现,它也是唯一的 Window 实现类,PhotoWindow 又创建了一个 DecorView(间接的继承自View)作为整个Activity的根布局。DecorView 被分为两部分:ActionBar 部分(一般开发过程中都会隐藏,采用 google 推荐的 ToolBar)和 id 为 content的FragmentLayout部分,我们 setContentView(@LayoutRes int layoutResID) 设置的Activity XML布局就是在FragmentLayout中
4.view生命周期
- onFinishInflate() 当View中所有的子控件均被映射成xml后触发
- onMeasure( int , int ) 确定所有子元素的大小
- onLayout( boolean , int , int , int , int ) 当View分配所有的子元素的大小和位置时触发
- onSizeChanged( int , int , int , int ) 当view的大小发生变化时触发
- onDraw(Canvas) view渲染内容的细节
- onKeyDown( int , KeyEvent) 有按键按下后触发
- onKeyUp( int , KeyEvent) 有按键按下后弹起时触发
- onTrackballEvent(MotionEvent) 轨迹球事件
- onTouchEvent(MotionEvent) 触屏事件
- onFocusChanged( boolean , int , Rect) 当View获取或失去焦点时触发
- onWindowFocusChanged( boolean ) 当窗口包含的view获取或失去焦点时触发
- onAttachedToWindow() 当view被附着到一个窗口时触发
- onDetachedFromWindow() 当view离开附着的窗口时触发,Android123提示该方法和 onAttachedToWindow() 是相反的。
- onWindowVisibilityChanged( int ) 当窗口中包含的可见的view发生变化时触发
自定义view实现方式分为四类:
- 继承五大布局(已经帮我们写好了一些容器规则),组合控件
- 继承viewgroup,流式布局
- 继承原生控件(textview,xrecyclerview,xlistview)
- 继承view