##前言:
- 仅仅使用系统的控件是不够的,使用自定义View可以实现更棒的效果。
- 自定义View是一个综合的技术体系。设计View的层次结构,时间分发机制和View的工作原理等技术细节,所以自定义初学者当然会觉得自定义View比较难(认同!!!)。
所以将从一定的高度来理解自定义View,通过现象看本质,避免陷入只见树木不见森林的状态。
##1. 分类:
- 继承View从写onDraw()方法
采用这种方式需要自己支持wrap_content,并且padding也需要自己处理。 - 继承ViewGroup派生特殊的Layout
当效果看起来很像集中View组合在一起的时候,可以采用这种方法来实现。 - 继承特定的View
一般用于扩展某种已有的View的功能。比如继承TextView进行增强等。 - 继承特定的ViewGroup
比如继承LinearLayout进行增强等,或者继承RelativeLayout写组合控件。
##2. 自定义View注意事项:
- 让View支持wrap_content
直接继承View或ViewGroup的控件,如果不支持wrap_content,则该控件的表现效果和match_parent一样。 - 如果有必要,支持padding
直接继承View的控件,不在draw()方法中处理padding,则padding属性失效。继承ViewGroup的控件必须要在onMeasure()和onLayout()中考虑padding和margin,否则这两属性失效。 - 尽量不要在View中使用Handler
View本身就提供了post系列方法,完全可以替代handler。除非很明确地要使用handler。 - View中如果有线程或动画,需要及时停止
在View.onDetachedFromWindow()
中停止。如果不及时处理,会造成内存溢出。当包含此View的Activity退出或者此View被remove()时,就会调用该方法。 - View带有滑动嵌套情形时,需要处理好滑动冲突
##3. 获取View的宽高
- 在onWindowFocusChanged()中获取,但可能被频繁调用
- view.post(runnable)中获取,加入到消息队列尾部
- 使用ViewTreeObserver