上一篇:android onMeasure 实现

上一篇中其实对测量讲解的比较清楚了,对布局没有说。不过对于 viewGroup而言,测量完成了,也就意味着着,知道怎么布局了。

其实知道了怎么测量和布局就可以实现很多沙雕的控件了。比如流布局。当然了,如果想提供很方便的调用方式,还需要搞一些便捷的自定义属性才行。

这里展示一下,通过测量和布局实现的沙雕布局。

android 自定义控件中的测量和布局

android 自定义控件中的测量和布局

通过效果图可以看出来,这就是流布局了。而且带两种效果:一种就是普通的流布局,一行一行的排列;然后第二种是竖直排列的效果,是一列一列的排列。

当然了,这两种的代码差别其实不大,主要是 在测量和布局的时候,要计算好每个 item 应该占据的尺寸和位置。

大致说一下原理。

比如这种横向排列的流布局。在测量的时候,首先肯定也是测量每个 child的宽高。然后需要判断,当前这个 child是挨着上一个的后面继续排,还是换行。然后对于布局,也是一样的,如果不换行,那么当前这个 child一定是排在上一个的后面,就要计算好当前的childl,t,r,p(上下左右四个顶点)对应的位置距离。如果换行,也是要计算这4个值。只是计算的逻辑有区别。

核心逻辑,关于计算和判断是否需要换行的代码就是下面这几行:

	if (lineWidth + itemW > ws - getPaddingLeft() - getPaddingRight()) {
	    // 换行 ,先记录换行之前的数据
	     width = Math.max(width, lineWidth); // 记录的是上一行的数据
	     height += lineHeight; // 记录的是上一行的数据
	
	     // 换行了
	     lineHeight = itemH;
	     lineWidth = itemW;
	 } else {
	     // 不换行
	     lineHeight = Math.max(lineHeight, itemH);
	     lineWidth += itemW;
	 }
	
	 if (i == count - 1) {
	     // 最后一个 view , 记录这一行的数据
	     width = Math.max(width, lineWidth); // 记录的是这一行的数据
	     height += lineHeight; // 记录这一行的数据
	
	 }
	 // width/height 是 将要设置给自己(当前自定义的这个ViewGroup)的宽度/高度

看起来代码很少,而且也容易理解。但是,我要说的是,就是这里的逻辑搞得我头大,我之前想了很久,代码写的比这里复杂多了,但是没有实现想要的效果。(就是可以继续挨着就挨着,否则换行的效果)

实在没有想到要怎么实现这个逻辑,然后查了一些资料,终于写成上面这样的代码了。(可以说上面的这几行代码并非原创。)

要特别注意当前计算出来的值,是当前行的数据,还是上一行的数据。一定要计算出当前行的。

然后要注意对 child支持padding / margin的设置支持。(也是在测量和布局的时候做的逻辑)

彩蛋来了完整代码,star me

相关文章: