Kotlin实现流式布局
本篇旨在使用kotlin代码实现TextView的流式排版,采用继承于ViewGroup的形式进行构建。
流式布局采用的方式是由左至右,由上至下的形式。简单的理解就是textview先排满一行后,再排下一行。按照此方式,我们可以确定,每一行应该由一个TextView的集合,同时也应该会确定一个统一的行高:
/**
* 行视图集合
*/
class FlowChips {
/**
* 子视图
*/
var views: MutiableList<View> = mutableListOf()
/**
* 行高
*/
var rowHeight: Int = 0
}
以下开始实现FlowLayout:
class FlowLayout : ViewGroup {
private val DEBUG: Boolean = false
private val TAG: String = "FlowLayout"
/**
* 列间隔
*/
private var mHorizontalSpacing: Int = 10
/**
* 行间隔
*/
private var mVerticalSpacing: Int = 10
private val chipArray: MutableList<FlowChips> = ArrayList<FlowChips>()
constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
constructor(
context: Context?,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) : super(context, attrs, defStyleAttr, defStyleRes)
@SuppressLint("DrawAllocation")
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
chipArray.clear()
val selfWidth = MeasureSpec.getSize(widthMeasureSpec)
val selfHeight = MeasureSpec.getSize(heightMeasureSpec)
val selfHeightMode = MeasureSpec.getMode(heightMeasureSpec)
val selfWidthMode = MeasureSpec.getMode(widthMeasureSpec)
var rowChips = FlowChips()
var rowHeight: Int = 0;
var rowWidthUsed: Int = 0;
var totalHeight: Int = 0;
for (i in 0 until childCount) {
val childView = getChildAt(i)
val lp = childView.layoutParams
val childWidthMeasureSpec = getChildMeasureSpec(MeasureSpec.makeMeasureSpec(selfWidth, selfWidthMode), childView.paddingStart + childView.paddingEnd, lp.width)
val childHeightMeasureSpec = getChildMeasureSpec(MeasureSpec.makeMeasureSpec(selfHeight, selfHeightMode), childView.paddingTop + childView.paddingBottom, lp.height)
childView.measure(childWidthMeasureSpec, childHeightMeasureSpec)
var rowHeightTemp = rowHeight.coerceAtLeast(childView.measuredHeight)
var widthUsedTemp = rowWidthUsed
widthUsedTemp += childView.measuredWidth
if (widthUsedTemp > selfWidth) {
// 超过父View宽度
// 此行结束,换行
totalHeight += rowHeight + mVerticalSpacing;
chipArray.add(rowChips)
rowChips = FlowChips()
rowWidthUsed = childView.measuredWidth
rowHeight = childView.measuredHeight
rowChips.rowHeight = rowHeight;
rowChips.views.add(childView)
} else {
rowWidthUsed = widthUsedTemp + mHorizontalSpacing
rowChips.rowHeight = rowHeightTemp;
rowChips.views.add(childView)
}
if (i == childCount - 1) {
totalHeight += rowHeight + mVerticalSpacing
rowChips.rowHeight = rowChips.rowHeight.coerceAtLeast(rowHeight)
chipArray.add(rowChips)
}
}
setMeasuredDimension(widthMeasureSpec, MeasureSpec.makeMeasureSpec(totalHeight.coerceAtLeast(selfHeight), selfHeightMode))
}
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
var currentLeft = paddingStart
var currentTop = paddingTop
for(chips in chipArray) {
for(view in chips.views) {
var start = currentLeft;
var top = currentTop;
var end = start + view.measuredWidth
var bottom = top + view.measuredHeight
view.layout(start, top, end, bottom)
currentLeft = end + mHorizontalSpacing
}
currentLeft = paddingStart
currentTop += chips.rowHeight + mVerticalSpacing
}
}
}
完结

浙公网安备 33010602011771号