自定义ViewGroup之TagLayout
2020-07-25 本文已影响0人
卖炭少年炭治郎
package com.okay.mvdemo
import android.content.Context
import android.graphics.Rect
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import androidx.core.view.children
import kotlin.math.max
/**
* @author : zyl
* @desc :
*/
class TagLayout(context: Context?, attrs: AttributeSet?) : ViewGroup(context, attrs) {
private val childBounds = arrayListOf<Rect>()
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
var widthUsed = 0
var heightUsed = 0
var lineWidthUsed = 0
var lineMaxHeight = 0
val widthSpecMode = MeasureSpec.getMode(widthMeasureSpec)
val widthSpecSize = MeasureSpec.getSize(widthMeasureSpec)
for ((index, child) in children.withIndex()) {
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, heightUsed)
//保证每个子view只会创建一个rect
if (index >= childBounds.size) {
childBounds.add(Rect())
}
//如果是UNSPECIFIED 拿不到具体宽度值
if (widthSpecMode != MeasureSpec.UNSPECIFIED && widthSpecSize < lineWidthUsed + child.measuredWidth) {
//需要折行
heightUsed += lineMaxHeight
lineWidthUsed = 0
lineMaxHeight = 0
//折行之后已用高度变了 所以需要重新测量
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, heightUsed)
}
val rect = childBounds[index]
rect.set(
lineWidthUsed,
heightUsed,
lineWidthUsed + child.measuredWidth,
heightUsed + child.measuredHeight
)
lineWidthUsed += child.measuredWidth
widthUsed = max(lineWidthUsed,widthUsed)
lineMaxHeight = max(lineMaxHeight, child.measuredHeight)
}
val selfWidth = widthUsed
val selfHeight = lineMaxHeight + heightUsed
setMeasuredDimension(selfWidth, selfHeight)
}
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
for ((index, child) in children.withIndex()) {
val childBound = childBounds[index]
child.layout(childBound.left, childBound.top, childBound.right, childBound.bottom)
}
}
override fun generateLayoutParams(attrs: AttributeSet?): LayoutParams {
return MarginLayoutParams(context, attrs)
}
}