您的位置:首页 > 移动开发 > Android开发

【Android View绘制之旅】Layout过程

2017-01-31 22:07 369 查看

1.为什么要进行Layout?

【Android View绘制之旅】View之测量Measure过程后,View我们得到View的宽高,但光只有宽高值是不足以反映视图的,更需要知道View所在的位置。

Layout第一步:layout()方法

【Android View绘制之旅】View之测量Measure里也说过,我们的视图树就是从线性布局开始的,所以我们仍旧是从LinearLayout研究起。

同measure一样,LinearLayout没有覆写layout方法,那么直接就看View的。

虽然View的layout方法没有加final,但是明确禁止覆写。

Derived classes should not override this method. Derived classes with children should override onLayout. In that method, they should call layout on each of their children.



layout方法的入参

入参由当前View的父组件计算得来的,具体见下面的分析。

代码中主要值得关注的地方有如下两处:

设置自身位置并判断位置同上次有无变化 见代码块A

setFrame() :layout结果执行的关键一步



判断一下跟Parent View的相对位置有没有发生变化

判断一下宽高有没有变化sizeChanged,有变化则invalidate一下(到后面draw部分可以探究)

将新的位置值赋值给当前View。

了解View布局的关键结果:mLeft,mRight,mTop,mBottom

拿mLeft来说,他是自身左边到父View的左边的距离,以像素为单位。

The distance in pixels from the left edge of this view’s parent to the left edge of this view.



他们都是距离上边和左边的距离

位置同上次有变化,则执行onLayout 见代码块B

View的onLayout的实现为空,自身位置的设置已经在上面setFrame做过了,在onLayout里一般在当前View内嵌有子View的时候去遍历所有子View并逐一调用他们的layout方法。

线性布局的onLayout()方法

仍旧以代表性的layoutVertical为例子深入分析,

几个局部变量的意义

* majorGravity:线性布局垂直方向上的gravity设置

* minorGravity:线性布局水平方向上的gravity设置

* mTotalLength:分割线高度+ 子组件高度并包含自身上下Margin + 线性布局自身上下padding.

几个主要过程(layout()方法入参是如何计算出来的?在这里能找到答案):

childTop的求解

需要考虑靠上或下或居中的情况。



我们在说到是靠上 靠下 还是居中是有个前提的,就是线性布局除了容纳子组件外还有富余的空间。

富余的空间= bottom - top - mTotalLength


靠上 靠下 还是居中都是如何”处理”这些富余空间的策略而已。拿Gravity.BOTTOM来说吧:其实就是将富余空间放到上边,那么从垂直方向来说,子组件是从mPaddingTop + bottom - top - mTotalLength 开始的,(当然我们还要包括线性布局自身上部的padding.)

childLeft的求解

需要考虑靠上或下或居中的情况。



几个局部变量的意义

* width:当前线性布局的宽度

* childSpace:线性布局横向上除去padding后留给子组件的可用空间

问题:childLeft是子组件左侧到父组件左边的距离,那childLeft包含其自身的leftMargin吗?

拿左侧对齐的代码来说:

childLeft = paddingLeft + lp.leftMargin;


理解如下图:



一目了然,childLeft是不包含其自身的leftMargin,那么其他的如Top,Right类似。

childLeft的求解比较好理解就不多言了。有了上边及左边的位置,childBottom,childRight底部 和右边的位置就唾手可得了。

private void setChildFrame(View child, int left, int top, int width, int height) {
child.layout(left, top, left + width, top + height);
}


View的getMeasureWidth/Height和getWidth/Height的区别是?



说了这么多,Layout的结果是什么?

mLeft

mTop

mRight

mBottom

拥有了更新的值,这个确定了后,相对于其在父组件中的相对位置就确定了,再不停的向外延伸考虑,相对再相对,这个值确定的意义就在于其在整个视图中的绝对位置被确定了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android