View工作原理(三)——自定义View

之前暑假本来写了这方面的学习笔记,但由于给出的事例一直没有来得及写讲解所以一直在草稿箱里。今天,我准备重新写一下这里的总结。自定义View有四个构造函数,第二个构造函数是我们在xml里写我们的View时会调用的,所以如果后面用到context注意要在这里初始化或者调用三参构造,并在三参构造里初始化。首先,要先理解一下自定义View的SpecMode有三种模式,这样会使你的自定义View更正...
摘要由CSDN通过智能技术生成

自定义View

什么是?

自定义View就是自己设计出来的View,一般继承View或ViewGroup或已有的控件和布局。自己处理View的三个过程:测量、布局、绘制。并处理可能产生的一些问题:如滑动冲突,事件处理等等。需要对View的工作原理、事件分发及滑动冲突处理有一定了解。如果需要很炫的动画,也需要对动画有一定的了解。

为什么要用自定义View?

实现一些系统控件不能实现的特效,功能,而且自定义View十分的灵活,比如你要实现一个选票控件,课程表控件,日期选择控件等等,当然你也可以使用开源框架,但是有些业务逻辑用开源框架并不能对业务逻辑进行很好的控制。

自定义View须知(一些需要注意的问题)
1.让View支持warp_content

直接继承View和ViewGroup的控件,如果不处理wrap_content,会导致可能不会实现预期效果,原因在:View工作原理二说过,wrap_content不处理时为AT_MOST模式,也就是和match_partent的大小一样。

2.支持padding和margin

对于直接继承View的需要处理padding,如果不处理会导致padding失效,但margin有作用,因margin是父容器实现的;对于直接继承ViewGroup的需要处理padding和子元素的margin,不然会导致padding和子元素的margin失效。

3.尽量不要在View中使用Handler

因为View内部本身就提供了post系列的方法,可以完全替代Handler作用,除非你很明确需要用Handler发消息。

4.View中如果有线程或者动画,需要及时停止,参考View#onDetachedFromWindow

当包含此View的Activity退出或者当前View被remove的时候onDetachedFromWindow方法会被调用,这时就是停止动画和线程的很好的时机;和这个方法对应的是onAttachedWindow,当包括此View的Activity启动时,View的onAttachedToWindow会被调用。当View变得不可见时我们也需要停止线程和动画,防止内存泄漏。

5.View具有滑动嵌套情形时,需要处理好滑动冲突
自定义View的分类
1.继承View重写onDraw方法

需要自己处理wrap_content和padding。

2.继承ViewGroup

需要自己处理ViewGroup的测量和布局过程。

3.继承特定的View(如:TextView、ImageView)

不需要自己支持wrap_content和padding。

4.继承特定的ViewGroup(如:LinearLayout、FrameLayout)

不需要处理ViewGroup的测量和布局这两个过程。
自定义View有四个构造函数,第二个构造函数是我们在xml里写我们的View时会调用的,所以如果后面用到context注意要在这里初始化或者调用三参构造,并在三参构造里初始化。
首先,要先理解一下自定义View的SpecMode有三种模式:
①UNSPECIFIED:父容器不对View有任何的限制,要多大给多大,这种情况一般用于系统内部,表示一种测量状态。
②EXACTLY: 父容器已经测量出View所需要的精确大小,这个时候View的最终大小就是SpecSize所指定的值。它对应于LayoutParams中的match_parent具体的数值这两种模式。
③AT_MOST: 父容器指定了一个可用大小即SpecSize,View的大小不能大于这个值,具体是什么值要看不同的View的具体实现。它对应于LayoutParams中的warp_content。所以在写自定义View的时候一定要重写onMeasure()方法 ,去适配WRAP_CONTENT的情况,因为WRAP_CONTENT情况为AT_MOST模式,不设置会和MATCH_PARENT的效果一样,也许你在使用的时候对你的界面好像并没有什么影响,单这样复用性很不好,也就是说你下次再要做一个和这个类似的东西你可能还要去适配大小。

还有一点需要注意,不要在onMeasure中去获取宽高,因为可能不准确,最好在onLayout中去获取宽高,onMeasure中的两个参数widthMeasureSpec、heightMeasureSpec我打印出来的值是1073742904,-2147482016,getHeight()打印出来的值为0,点进去一看getHeght{ return mBottom - mTop;},mBottom,mTop的值是在onLayout的时候才去初始化的,所以在onMeasure中难以获取到准确的测量值。我这里继承View的onMeasure走了两遍,子元素的MeasureSpec是由

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值