参考博文地址 添加链接描述
import android.content.Context
import android.graphics.Rect
import android.util.AttributeSet
import android.util.Log
import android.view.ViewGroup
public class MyViewGrop @JvmOverloads constructor
(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0)
:ViewGroup(context,attrs,defStyleAttr) {
private var listRect= mutableListOf<Rect>()
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
//用了多好宽高
var widthused=0
var heightused=0
//每一行用了多少宽高
var linewidthused=0
var lineheight=0
//取出自己的宽度限制
var widthMode = MeasureSpec.getMode(widthMeasureSpec)
var widthSize = MeasureSpec.getSize(widthMeasureSpec)
if (listRect.isEmpty()) {
for (index in 0 until childCount) {
Log.e("TAG","初始化:"+index)
listRect.add(Rect())
}
}
for ( index in 0 until childCount){
val childView = getChildAt(index)
measureChildWithMargins(childView,widthMeasureSpec,0,heightMeasureSpec,heightused)
//如果算出来的 宽度 比自己的宽度还大那就要重新测量 准备换行
if (widthMode!=MeasureSpec.UNSPECIFIED&&linewidthused+childView.measuredWidth>widthSize){
//既然是重新测量了 那显然 每行已经用掉的宽度就是0了
linewidthused = 0
//计算已经用了多少高度了 因为既然换行了 heightUsed 就要增加了
heightused +=lineheight
measureChildWithMargins(childView,widthMeasureSpec,0,heightMeasureSpec,heightused)
}
val rect = listRect[index]
//起点的left和top 很好理解 就是 这一行 已经用了多少 你就从这个位置开 layout
rect.set(linewidthused,heightused,
linewidthused+childView.measuredWidth,heightused+childView.measuredHeight)
//每一行已经用的 当然是加上这个child的宽度
linewidthused += childView.measuredWidth
//计算一下最大宽度 到时候自己要用
widthused=Math.max(linewidthused,widthused)
//每一行的高度 就等于这一行里面 高度最大的那个view
lineheight= Math.max(lineheight, childView.measuredHeight)
}
//子view 都算出来了 那我自己也肯定就算出来了吧
val measureWidth = widthused
val measureHeight = (heightused + lineheight)
//算完了以后 直接调用这个方法 到这里测量就全部结束了
setMeasuredDimension(measureWidth, measureHeight)
}
override fun onLayout(p0: Boolean, p1: Int, p2: Int, p3: Int, p4: Int) {
if (listRect.isNotEmpty()) {
for (index in 0 until childCount step 1) {
val child = getChildAt(index)
val childBounds = listRect[index]
child.layout(
childBounds.left,
childBounds.top,
childBounds.right,
childBounds.bottom
)
}
}
}
override fun generateLayoutParams(attrs: AttributeSet?): LayoutParams {
return MarginLayoutParams(context,attrs)
}
}