Android 自定义View知识点

自定义View知识点

自定义View我们需要了解View的绘制机制和ViewGroup的绘制机制,了解之后我们就可以在系统预留的方法里进行自定义View的工作了。

1、MeasureSpec
模式说明
UNSPECIFIED父容器不对View有任何限制,给它想要的任何尺寸。一般用于系统内部,表示一种测量状态。
EXACTLY父容器已经检测出view的精确大小,这时候view的大小就是size所指定的值。它对应于LayoutParams中的match_parent和具体数值两种模式。
AT_MOST父容器指定了一个可用大小,即size,子view的大小不能大于这个值,具体值要看vew的实现。它对应于LayoutParams中的wrap_content。

MeasureSpec是受到自身的LayoutParams和父容器的MeasureSpec共同影响的。

2、Measure
1、View的Measure过程

1.View调用onMeasure方法,onMeasure方法里调用了setMeasuredDimension方法,setMeasuredDimension方法又调用了getDefaultSize方法。

2.调用setMeasuredDimension方法,该方法是用来设置View的宽高的。

3.setMeasuredDimension方法调用了getDefaultSize方法,该方法根据传入的不同的MeasureSpec和size进行测量返回不同的测量结果。在AT_MOST和EXACTLY模式下,返回MeasureSpec.getSize方法返回的值,在UNSPEXIFIED方法里返回传入的大小值。根据上面的MeasureSpec表可知,对于直接继承View自定义的View而言,wrap_content和match_parent是一样的,所以我们要重写onMeasure方法。

4.getDefaultSize方法传入的参数调用了getSuggestedMinimumWidth()和getSuggestedMinimumHeight()方法。这两个方法会根据View是否有背景来返回测量的值。如果没有背景则返回mMinWidth或者mMinHeight,mMin的值是可以在View里设置的,通过setMinimumWidth或者setMinimumHeight即可设置;如果有背景则返回mMinWidth或者mMinHeight和mBackground.getMinimumWidth或mBackground.getMinimumHeight中的最大值。

2、ViewGroup的Measure过程

1.ViewGroup不只要测量自身,还要便利测量子元素的measure方法。ViewGroup里没有提供onMeasure方法,但是它有measureChildren方法。

2.在measureChildren方法里面它调用了getChildMeasureSpec方法。有意思的是我们可以在这张表里找到一个switch语句,里面有父View和子View测量模式最终返回的不同的结果,如图所示

父View测量模式子View LayoutParams最终测量模式
EXACTLY具体值EXACTLY
EXACTLYMATCH_PARENTEXACTLY
EXACTLYWRAP_CONTENTAT_MOST
AT_MOST具体值EXACTLY
AT_MOSTMATCH_PARENTAT_MOST
AT_MOSTWRAP_CONTENTAT_MOST
UNSPECIFIED具体值EXACTLY
UNSPECIFIEDMATCH_PARENTUNSPECIFIED
UNSPECIFIEDWRAP_CONTENTUNSPECIFIED

需要注意的是,当父容器的测量模式为AT_MOST时,子View的LayoutParams为WRAP_CONTENT,根据上图则可以发现子元素的测量模式也是AT_MOST,要解决这个问题需要在LayoutParams里制定以下默认的宽和高。

3、Layout

layout方法的作用是确定View的位置。
layout有四个参数,分别是l、t、r、b分带是View从左上右下相对其父容器的位置。layout方法会调用setFrame方法,而setFrame方法也有四个参数,正是layout方法穿进去的四个参数。调用setFrame方法后会调用onLayout方法,而onLayout方法是个空方法。需要我们根据不同的需求去实现。

4、Draw

draw的流程如下:
1、绘制 backgroud(drawBackground) ;
2、如果需要的话,保存canvas的layer,来准备fading ;
3、绘制view的content(onDraw方法);
4、绘制children(dispatchDraw方法);
5、如果需要的话,绘制fading edges,然后还原layer ;
6、绘制装饰器、比如scrollBar(onDrawForeground);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值