关于自定义View,ViewGroup的一点经验总结

View的三次measure,两次layout和一次draw

- Activity的生命周期和它包含的View的生命周期的关系 


在onCreate函数中,我们通常都调用setContentView来设置布局文件,此时Android系统就会读取布局文件,但是视图此时并没有加载到Window上,并且也没有进入自己的生命周期。 

只有等到Activity进入resume状态时,它所拥有的View才会加载到Window上,并进行测量,布局和绘制。所以我们会发现相关函数的调用顺序是:

onResume(Activity)

onPostResume(Activity)

onAttachedToWindow(View)

onMeasure(View)

onMeasure(View)

onLayout(View)

onSizeChanged(View)

onMeasure(View)

onLayout(View)

onDraw(View)



自定义View常用方法执行顺序

CYView: MyView(2):

CYView: onFinishInflate:

CYView: onAttachedToWindow:

CYView: onMeasure:

CYView: onMeasure:

CYView: onSizeChanged:

CYView: onLayout:

CYView: onWindowFocusChanged:

CYView: onMeasure:

CYView: onLayout:

CYView: onDraw:

CYView: dispatchDraw:

自定义ViewGroup常用方法执行顺序

D/CYViewGroup: onFinishInflate:

D/CYViewGroup: onAttachedToWindow:

D/CYViewGroup: onMeasure:

D/CYViewGroup: onMeasure:

D/CYViewGroup: onSizeChanged:

D/CYViewGroup: onLayout:

D/CYViewGroup: onWindowFocusChanged:

D/CYViewGroup: onMeasure:

D/CYViewGroup: onLayout:

D/CYViewGroup: onDraw://绘制背景时回调了onDraw()D/CYViewGroup: dispatchDraw:

ViewGroup嵌套View时方法的执行顺序

CYViewGroup: MyViewGroup(2):

CYView: MyView(2):

CYView: onFinishInflate:

CYViewGroup: onFinishInflate:

CYViewGroup: onAttachedToWindow:

CYView: onAttachedToWindow:

CYViewGroup: onMeasure:

CYView: onMeasure:

CYViewGroup: onMeasure:

CYView: onMeasure:

CYViewGroup: onSizeChanged:

CYViewGroup: onLayout:

CYView: onSizeChanged:

CYView: onLayout:

CYViewGroup: onWindowFocusChanged:

CYView: onWindowFocusChanged:

CYViewGroup: onMeasure:

CYView: onMeasure:

CYViewGroup: onLayout:

CYView: onLayout:

CYViewGroup: onDraw://仅当ViewGroup绘制背景时才执行CYViewGroup: dispatchDraw:

CYView: onDraw:

CYView: dispatchDraw:


继承View重写onDraw方式 

这种方式主要用来实现一些不规则的自定义View 

需要自己处理wrap_content的情况 因为默认的View对wrap_content没做特殊处理,只把这种情况当做match_parent处理 而且padding也需要自己处理 margin不用 因为margin是父容器确定的

继承ViewGroup派生特殊的Layout 

这种方式稍微复杂一些,它需要处理onMeasure和onLayout这两个函数 完成测量和布局的工作 并且需要自行处理wrap_content情况

继承特定的View(比如TextView等) 

此种方式比较常见,一般用于扩展一种已经存在的View的功能 此方法比较容易实现 不需要自己处理 wrap_content和padding

继承特定的ViewGroup(比如LinearLayout) 

此种方式比较常见,相比第二种方法简单许多,因为它已经有默认的onMeasure和onLayout的实现 并且已经处理了wrap_content和padding 

通常这种方式和方法二的实现是互通的 ,这个方法可以实现的方法二也可以实现,方法二能实现的这个也能实现,只不过方法二比较麻烦,但是贴近底层,贴近底层效率就会高一点,方法四比较简单

让View支持wrap_content 

直接继承View或ViewGroup的控件 都不支持wrap_content 方法 需要在onMeasure方法中设置

如果有必要 支持padding 

直接继承View的控件,如果不在onDraw方法中处理padding 那么padding属性是无法起作用的 直接继承ViewGroup的控件,需要处理padding和子元素的margin对其的影响,否则这两个属性也无效

尽量不要在view中使用handler 因为view提供了post方法 

View内部本身就提供了post系列方法 可以代替handler 但如果明确需要Handler 可以使用

view中有线程或者动画 要及时停止 

这是为了防止内存泄漏,可以在onDetachedFromWindow方法中结束,这个方法回调的时机是 当View的Activity退出或者当前View被移除的时候 会调用 这时候是结束动画或者线程的好时机 另外还有一个对应的方法 onAttachedToWindow 这个方法调用的时机是在包含View的Activity启动时 回调 回调在onDraw方法 之前

有嵌套滑动效果时 注意处理滑动冲突 





- Activity初始化时View为什么会三次measure,两次layout但只一次draw? 

- ViewRoot的初始化过程

你可能感兴趣的:(关于自定义View,ViewGroup的一点经验总结)