一个很low的viewgroup改写
程序员文章站
2022-03-07 18:22:31
改写一个随着子控件的摆放,当到达viewgroup的宽度时自动换行的view思路:在onMeasure里计算控件的宽高并计算好摆放的位置,然后根据父控件的宽度来考虑是否要换行直接上代码:package com.example.opencvapplicationimport android.content.Contextimport android.graphics.Rectimport android.graphics.RectFimport android.util.Attribu...
改写一个随着子控件的摆放,当到达viewgroup的宽度时自动换行的view
思路:在onMeasure里计算控件的宽高并计算好摆放的位置,然后根据父控件的宽度来考虑是否要换行
直接上代码:
package com.example.opencvapplication
import android.content.Context
import android.graphics.Rect
import android.graphics.RectF
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.view.ViewGroup
import androidx.core.view.children
import androidx.core.view.marginBottom
import androidx.core.view.marginTop
import kotlin.math.max
class SteamViewGrop(context: Context?, attrs: AttributeSet?) : ViewGroup(context, attrs) {
val rectList = ArrayList<Rect>()
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec)
var startLeft = 0
var startTop = 0
var maxHeight = 0
var usedHeight = 0
val viewWidth = MeasureSpec.getSize(widthMeasureSpec)
val viewHeight = MeasureSpec.getSize(widthMeasureSpec)
Log.e("xxj", "viewWidth=$viewWidth")
for ((index, child) in children.withIndex()) {
//计算子控件的宽高
measureChildWithMargins(child,widthMeasureSpec,0,heightMeasureSpec,viewHeight-usedHeight)
val margin = child.layoutParams as MarginLayoutParams
maxHeight =max(maxHeight, child.measuredHeight + margin.bottomMargin + margin.topMargin)//取当前行最大的高度
if (startLeft + child.measuredWidth > viewWidth) {//当宽度大于父控件的宽度时换行
startTop += maxHeight
usedHeight += maxHeight
maxHeight = 0
startLeft = 0
//重新计算宽高
measureChildWithMargins(child,widthMeasureSpec,0,heightMeasureSpec,viewHeight-usedHeight)
}
Log.e("xxj", "startLeft=$startLeft startTop=$startTop child.width=${child.measuredWidth}")
if (index >= rectList.size) {
rectList.add(Rect())
}
rectList[index].set(//设置子控件的位置
startLeft + margin.leftMargin,
startTop + margin.topMargin,
startLeft + margin.leftMargin + child.measuredWidth,
startTop + margin.topMargin + child.measuredHeight
)
startLeft += child.measuredWidth + margin.rightMargin
}
usedHeight += maxHeight
setMeasuredDimension(viewWidth, usedHeight)
}
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
for ((index, child) in children.withIndex()) {
child.layout(
rectList[index].left,
rectList[index].top,
rectList[index].right,
rectList[index].bottom
)
}
}
override fun generateLayoutParams(attrs: AttributeSet?): LayoutParams {
return MarginLayoutParams(context, attrs)
}
}
使用:
<?xml version="1.0" encoding="utf-8"?>
<com.example.opencvapplication.SteamViewGrop xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.MainActivity">
<TextView
style="@style/textStyle"
android:text="伊利丹" />
<TextView
style="@style/textStyle"
android:text="维伦" />
<TextView
style="@style/textStyle"
android:text="基尔加丹" />
<TextView
style="@style/textStyle"
android:text="格鲁姆.地狱咆哮" />
<TextView
style="@style/textStyle"
android:text="玛法里奥.怒风" />
<TextView
style="@style/textStyle"
android:text="帕克" />
<TextView
style="@style/textStyle"
android:text="戴泽" />
<TextView
style="@style/textStyle"
android:text="卡尔" />
<TextView
style="@style/textStyle"
android:text="凯尔萨斯" />
<TextView
style="@style/textStyle"
android:text="瓦里安.乌瑞恩" />
</com.example.opencvapplication.SteamViewGrop>
本文地址:https://blog.csdn.net/xxj_1234562/article/details/107875378