如何自定义控件以及流程
1、measure过程总结
layout(ViewGroup)及其子view的测量过程:- 通过自身的MeasureSpec和子view的LayuoutParams,生成子view的MeasureSpec。这一步调用的是
getChildMeasureSpec(int spec, int padding, int childDimension)
方法。 - 调用子view的
measure(int widthMeasureSpec, int heightMeasureSpec)
方法,来测量子view的宽高。 - 在子view测量结束之后,根据情况来计算自身的宽高。假如自己的MeasureSpec是Exactly的,那么可以直接将SpecSize中的大小作为自己的宽或高;如果是wrap_content或者其他的,那么就需要在每一个子view测量完之后,调用子view的
getMeasuredHeight()
和getMeasuredWidth()
来获得子view测量的结果,然后根据情况计算自己的宽高。 - 使用
setMeasuredDimension(int measuredWidth, int measuredHeight)
方法保存测量的结果。
view的测量就更简单了:
因为没有子view,只要确定了自身内容的大小,再结合MeasureSpec便可以测量完毕。比如有个view需要画个圆,那么只要考虑设置的padding值以及圆的大小即可。
2、layout过程总结
layout的一般过程就是如此,总结起来就是如下几步:- 父layout在自己的
onLayout()
函数中负责对子view进行布局,安排子view的位置,并且将测量好的位置(上下左右位置)传给子view的layout()
函数。 - 子view在自己的
layout()
函数中使用setFrame()
函数将位置应用到视图上,并且将新位置和旧位置比较来得出自己的位置和大小是否发生了变化(changed),之后再调用onLayout()
回调函数。 - 如果此时子view中还有其他view,那么就在自己的
onLayout()
函数中对自己的子view进行第1布的布局操作,如此循环,只到最后的子view中没有其他view,这样就完成了所有view的布局。
当然,以上说的还是ViewGroup的layout过程,如果是View的layout过程就会更加简单,毕竟没有子view,只要将传进来的位置应用到视图上就OK。