一.初见View
- View的层级关系(Veiw到底分成几层,自定义view是从那一层开始绘制的)
R:Veiw树的结构如下 ,自定义View是从DecorView开始的;DecorView是View树的最顶层View,
- View树的遍历过程
- 父布局对View绘制模式的影响 (P182表)
4.为什么父view为wrap_parent时,继承的view布局为warp_parent行不通达不到预期效果?
5.如果在activity启动时获取某个view的尺寸,怎么获取?
onWindowsFocusChanges方法时获取
6.getwidth()和getMeasurewidth()有什么区别? - Touch事件分析 包含2个一个是 dispatchTouchEvent 和OnTouchEvent();
- 如何处理滑动冲突
二. MeasureSpec
1.由来:在View的测量过程中系统会将View的LayoutParams根据父容器所施加的规格转换成对应的MeasureSpec,然后偶再根据这个MeasureSpec来测量Veiw的宽高;
2.MeasureSpec是一个32位的int值,可以通过getMode和getSize来获取SpecMode和SpecSize;
3.SpecSize的有3种类型:
无限制类型unspecified | 精确类型exactly | 至多型at_most |
---|---|---|
无限制 | 对应match_parent和精确数值 | 对应于wrap_content |
2.1MeasureSpec和Layoutparams对应关系
4.顶层DecorView的MeasureSpec的产生,在ViewRootImpl中
|
|
由上可以得出 :
Layoutparmas.match_parent | wrap_parent | 精确(50dp) |
---|---|---|
精确模式,大小就是窗口大小 | 最大模式 at_most | 精确模式,大小就是制定大小 |
5.普通View的产生,由于View的measure是由ViewGrop传递而来
|
|
从上面的方法不难理解,他的代码主要是阐述根据父容器的MeasureSpec同时结合View本身的Layoutparams来确定子元素的MeasureSpec,列表如下
三. View的工作流程
View的工作流程主要是指Measure layout draw三个流程,即测量布局和绘制
3.1 View的测量
1.测量代码主要如下
由上面的代码可知在at_most和exactly的模式下,返回的view的specsize就是测量后的大小,(测量后的大小!=view的最终大小,最终大小是在layout时确定的),而unspecified,这种情况下,由上面代码可知
result=size,即宽高分别为传入值,那么这个传入值的方法是什么呢,往下看
|
|
从上面代码可以看出 如果view没有设置背景,view宽度对应xml里面的Android:minwidth属性所对应的值,如果没有指定即为0;如果有设置背景则取二者的较大值,
综合上面2段代码来看,也就很好的解释了开头的问题4,直接继承属性为wrap_parent的view的自定义控件需要重写onMeasure并设置其自身大小,因为如果父view为wrap,那么他的Specmode就是at_most,其子view如果是wrap属性,那么子veiw大小就是父控件的大小,和子view使用match_parent无异;
2 ViewGroup的测量
其实一开始我以为ViewGroup和View的测量代码是一样的都是调用onMeasure去完成,后来发现虽然逻辑上它的确是遍历所有子元素Measure方法然后子元素递归执行这个过程,但是实际上有点区别..由于
Viewgroup是一个抽象类,里面没有Onmeasure方法,他把测量工作交给了各个子类去实现,原因也是因为不同的布局是有不同的计算方式
3.2view的布局过程
- 先普及下坐标概念
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():获取点击事件距离整个屏幕顶边的的距离,即绝对坐标
- layout的作用是ViewGroup用来确定子元素的位置,当ViewGroup位置被确定后,他会遍历所有的子元素并调用其layout方法,layout确定veiw本身的位子,onLayout确定所有子元素的位子
|
|
在第12行通过setFrame设定View的四个顶点位置然后在调用onlayout方法去确定子Veiw的在Veiw中的位子;
- getwidth()和getMeasurewidth()有什么区别?
前者是最终的宽高,后者是测量的宽高,后者形成早于前者,如果一般默认情况下二者的确是相等的,但是如果我们自定义时人为更改,就会比测量的多出1001234@Overridepublic void layout(@Px int l, @Px int t, @Px int r, @Px int b) {super.layout(l, t, r+100, b+100);}
3.3View的绘制过程
draw过程的作用是将view绘制在屏幕上面
1.draw的步骤遵循以下几步
- 绘制背景 background.draw(canvas)
- 绘制自己 ondraw
- 绘制Children dispatchdraw
- 绘制装饰 ondrawScrollbars
源码里面其实写的也很清楚
|
|
###四.自定义Veiw的分类
- 继承View重新Ondraw()方法
- 继承viewGroup派生特殊的layout
- 继承特定的某个view
- 继承特定的viewGroup(LinearLayout)