Android MeasureSpec - View

MeasureSpec 是一个 32 位的 int 类型,并且取了最前面的两位代表 Mode,后 30 位代表大小 Size。

3种模式

EXACTLY(精确模式,在这种模式下,尺寸的值是多少,那么这个组件的长或宽就是多少,对应 MATCH_PARENT 和确定的值)

AT_MOST(WRAP_CONTENT,最大就是父控件的大小)

UNSPECIFIED(当前组件,可以随便用空间,不受限制,系统用,具体就体现在 NestedScrollView 和 ScrollView 中)

我们开发中,常用AT_MOST,EXACTLY

我们可能会给定默认大小,或者根据内容变化,经常都是固定大小

根视图
ViewRoot - performTraversals(执行遍历)

ViewGroup 还需要负责通知自己的子 View 进行绘制操作

private void performTraversals() {
    ...
    int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
    int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
    ...
    //执行测量流程
    performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
    ...
    //执行布局流程
    performLayout(lp, desiredWindowWidth, desiredWindowHeight);
    ...
    //执行绘制流程
    performDraw();
}

onMeasure

每个 View 都有自己的大小,所以基本自定义 View 的时候都需要重写 onMeasure() 这个方法,以定制化我们的 View 的宽高

如果不重写这个方法,我们通常会出现 wrap_content 和 match_parent 是一样的显示效果

View 默认是会使用 getDefaultSize() 方法进行设置宽高的,在 AT_MOST和 EXACTLY 两种情况下都会直接使用测量规格里面的尺寸

在 ViewGroup 中,并没有去重写 View 的 onMeasure() 方法,而这都需要它的子类根据自己的逻辑去实现
ViewGroup 提供了一个 measureChildren() 方法来依次遍历每个子 View 对其进行测量。
在经过 onMeasure() 操作后,getMeasureWidth() 和 getMeasureHeight() 方法就可以拿到正确的返回值了

由于 View 的 measure 过程和 Activity 的生命周期方法不是同步执行的,如果 View 还没有测量完毕,那么获得的宽/高就是 0。所以在 onCreate()、onStart()、onResume() 中均无法正确得到某个 View 的宽高信息。可以通过在 onWindowFocusChanged() 判断获取到焦点后进行获取,或者使用 view.post()方式。

onLayout

onLayout() 方法主要作用是确定子 View 的显示位置,由于 View 已经是最小的层级,所以我们在自定义 View 的时候通常不需要管这个方法,而在自定义 ViewGroup 的时候就不得不注意这个方法
通过确认left,top,right,bottom四个值,确定了view的大小
获取view的大小,可以在onSizeChange之后

draw

drawBackground()
onDraw()
dispatchDraw()
onDrawScrollbars()

通常我的内容就是在draw中,代码编写也是主要在这里

你可能感兴趣的:(Android MeasureSpec - View)