自定义View组件开发规范
一个开发出view组件应该是易用的,在使用时既可以使用默认的设置进行快速的配置,也可以在使用者需要更多的自定义化时提供足够的接口去控制view的样式与状态。这里的开发规范仅提示一些在进行自定义view开发中通用的需要注意的地方,更多时候规范需要的是根据使用者的需求与业务需求来制定。
自定义view的分类:
1. 继承特定的view(比如TextView)
这种方法比较常见,一般是用于扩展某种已有view的功能,比如TextView,这种方法比较容易实现,而且不需要自己支持wrap_content和padding等。
2. 继承特定的viewGroup(比如LinearLayout)
这种方法也比较常见,但某种效果看起来很像几种view组合在一起时,可以采用这种方式来实现。采用这种方式时不需要自己来处理viewGroup的测量和布局这两个过程。需要注意这种方法和方法4的区别,一般来说方法4能实现的效果方法2也都能实现,两者的主要差别在于方法4更接近view的底层。
3. 继承view重写onDraw方法
这种方法主要用于实现一些不规则的效果,即这种效果不方便通过布局的组合方式来达到,往往需要静态或者动态的显示一些不规则的图形。很显然这需要通过绘制的方式来实现,即重写onDraw
方法。采用这种方式时需要自己支持wrap_content,而且padding也需要自己来处理。
4. 继承viewGroup派生特殊的Layout
这种方法主要用于实现自定义的布局,即除了LinearLayout、RelativiLayout等这几种系统的布局之外,我们重新定义一种新布局,当某种效果看起来很像几种view组合在一起时,可以采用这种方法来实现。采用这种方式稍微复杂一些,需要合适地处理viewGroup的测量、布局这两个过程,并同时处理子元素的测量和布局过程。
自定义view须知
1.让view支持wrap_content
直接继承自view或者viewGroup的自定义组件,如果在onMeasure
中不对wrap_content进行特殊处理的话,那么当使用者在布局中使用了wrap_content时会无法达到预期的效果。解决的办法就是在自定义组件的onMeasure
时进行判断,如果布局中使用了wrap_content就给view指定一个默认的内部宽/高,而对于非wrap_content的情形就直接沿用系统的测量值。至于这个默认的内部宽/高的大小如何指定则没有固定的依据,根据需要灵活的配置即可。
2.有必要的话,让view支持padding
直接继承自view的自定义组件,如果不在draw方法中处理padding,那么padding属性是无法起作用的。另外直接继承自viewGroup的自定义组件需要在onMeasure
和onLayout
方法中考虑padding和子元素margin对其造成的影响,不然将会导致padding和子元素的margin失效。
3.尽量不在view中使用Handler
view内部本身提供了post系列方法,除了开发者明确要使用Handler来发送消息时,完全可以使用自带的post来代替Handler的作用。
4.及时停止view中的线程或动画
当自定义view中使用了线程或是动画效果时,需要在onDetachedFromWindow
方法中及时停止,否则会带来内存泄漏问题。
5.view带有滑动嵌套情景时,需要处理滑动冲突
当自定义view带有滑动效果时需要合适的处理滑动冲突,否则会严重影响view的效果。
6.自定义attr
当自定义view使用了自定义参数时,需要开发者在源码中或是或是文档中写出具体的参数使用方法以供他人查阅。另外在声明自定义参数的名称时要注意与其他自定义view的自定义参数要有明显的区别,应当在自定义参数前添加当前自定义view的标志作为前缀。
7.内部逻辑
尽量不要在自定义view中涉及指定项目的指定业务逻辑,自定义view应作为一个公用的组件可以在不同的项目、不同的业务情况下复用,涉及到业务逻辑的部分应提供相应接口以供外部处理调用。另外自定义view作为ui组件应该减少在绘制测量时的耗用时间以提供流畅的用户体验。
示例view
一个继承自View的自定义CheckBox,实现了自定义切换选中状态的动画特效,该自定义view便在onMeasure中实现了对wrap_content的支持。源码见Android-platform项目中customView.checkBox
包中的SmoothCheckBox.class
。
This blog is under a CC BY-NC-SA 3.0 Unported License
本文链接:http://yeguli.cn/2018/01/04/view组件开发规范/