1.每个View都只有一个父View
2.整个视图只有一个根View
3.DecorView --- FrameLayout
3.1我们在写视图的时候,要尽可能的少写视图层级
3.2能用FrameLayout写的,就不要用RelativiLayout,能用RelativiLayout写的,就不要用LinearLayout。
4.我们通过setContentView设置的View并不是最跟View。
4.1 隐藏标题栏需要在setContentView之前设置。
5.一个View如何显示到屏幕上来
5.1 view有多大-- measure --- onMeasure
5.2 view的位置在哪儿 -- layout --- onLayout
5.3 view长什么样子-- draw --- onDraw
6.不是所有的View都能添加子View
6.1 就是ViewGroup的子类,因为只有ViewGroup实现了ViewParent接口
6.2 我们通过getParent拿到的虽然是ViewParent,但是在它不为null的前提下,我们可以放心的强转为ViewGroup
7. measure
只有View有这个方法,ViewGroup没有重载
测量自身的大小
MeasureSpec:用来辅助计算View的大小
View.MeasureSpec.AT_MOST;// 最大
View.MeasureSpec.EXACTLY;//精确
View.MeasureSpec.UNSPECIFIED;//未知
目前未知没有使用,因为每一个View被添加到视图上时,都必须制定宽高,就算你不指定,也会有一个默认的(每个ViewGroup生成默认宽高都不一样)
通过MeasureSpec.makeMeasureSpec() 来合成模式和宽高
通过MeasureSpec.getMode和MeasureSpec.getSize 来获取模式和宽高
代码中设置View的宽和高必须要通过LayoutParams来设置,所有影响子View和父View之间的关系的属性全部需要通过LayoutParams来设置,也可以根据xml布局中属性名是否带有layout_开头来判断
LayoutParams有很多种类,基本上是每一种布局都有一个自己的实现,因为每个布局都有各自的特征,没办法用一个统一类来描述
如果父亲的mode是 EXACTLY, 子View是WRAP_CONTENT 那么mode 是AT_MOST, size 是父亲的最大size。
如果父亲的mode是 EXACTLY, 子View是MATH_PARENT 那么mode 是EXACTLY, size 是父亲的最大size。
如果父亲的mode是 EXACTLY, 子View是DIP 那么mode 是EXACTLY, size 是DIP。
如果父亲的mode是 AT_MOST, 子View是WRAP_CONTENT 那么mode 是AT_MOST, size 是父亲的最大size。
如果父亲的mode是 AT_MOST, 子View是MATH_PARENT 那么mode 是EXACTLY, size 是父亲的最大size。 // ---(大多数View实现都是EXACTLY,但是有些View实现是AT_MOST,我们要尽量避免这种情况)
如果父亲的mode是 AT_MOST, 子View是DIP 那么mode 是EXACTLY, size 是DIP。
如果你设定宽高为MATH_PARENT 或者 DIP 则模式为 EXACTLY,如果是WRAP_CONTENT,则为AT_MOST
如果你设定的宽高为DIP,那么你的size就是dip,其他情况都是父View的最大值,或者父View剩余的最大值
View内部是如何测量自身的
如果是一个包括内容的(540,50);
1.它会测量自己的背景图片 100*100
2.TextView 测量文字
ImageView测量自身的图片 200*200; ---> 50
200 200
ViewGroup --> 100 * 100
100 * 100
ViewGroup--> wrap wrap AT_MOST|100
100*100
ImageView是包裹内容的,但是设置的图片 200*200; AT_MOST|100
100*100
如果自身测量的结果大于父View传递过来的参数,并且模式是AT_MOST的时,它会选择一个较小的值
onMeasure
7.1 在一个View中,它是用来测量自身的大小,实际上就是设置自身的大小
7.2 在ViewGroup中,它通过onMeasure来测量子View的大小,并通过子View的大小来设置自身的大小。
view.measure(int,int);
8.layout(l,t,r,b)
在View中,是用来指定一个View的上下左右四个点,ViewGroup中没有重载
首先它用临时变量记录自己上一次的l,t,r,b,然后比较这一次的l,t,r,b。
if(l !=l || t !=t || r != r || b != b){
boolean changed = onSizeCHange
}
onLayout(changed)
8.1 在View中,它是空实现。因为一个View的位置是由它的父亲指定的。
8.2 在ViewGroup中,它是用来确定所有子View的位置。
ViewGroup的子类一般怎么实现该方法
LinearLayout --> 检查自身的方向orientation,判断是横向还是纵向
for循环遍历所有的子View。为子View准备l,t,r,b
如果是横向的,一般第一个View的l就是0,t就是0,r就是该View的宽度,b就是该View的高度。后面的View的l会等于前一个View的r。
RelativiLaytout --> for循环所有的子View。为子View准备l,t,r,b
首先它会获取这个子View的params,然后进行一些列的判断,根据其他子View确定该View的位置。
FrameLayout --> for循环所有的子View。为子View准备l,t,r,b
它就判断gravity,如果是start,就从左上角开始布局,
一般情况下,所有的子View都具备相同的l,t
9. draw
在View中,它是用来画一些通用的东西的。
如果你是View,它就会调用你的onDraw方法,
如果你是ViewGroup,它就会调用你的dispatchDraw