效果如下:
主要实现随窗口尺寸自动调整元素位置的功能,由于实际上考虑了window的尺寸(实现过程并未涉及window),在android上并不适用(虽然正常运行应该没有问题)。实现这种动态控件,思路还是很清晰的,就是用BoxWithConstraints测量待绘图区域的尺寸,根据得到的尺寸画出相应的控件。
代码如下:
import androidx.compose.foundation.layout.*
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import kotlin.math.floor
class TestUI2 {
/**
* 测试用数据
*/
data class TestData(
val id: Int,
val name: String,
val category: String,
val state: String,
)
@Composable
fun GridView(dataList:MutableList<TestData>) {
//对数据按类别和id排序
dataList.sortWith(compareBy({it.category},{it.id}))
/**
* 区间宽度,随窗口尺寸变化更新
*/
var districtWidth by remember { mutableStateOf(0f) }
/**
* 每个方框的尺寸
*/
val gridBoxWidth:Float=200f
/**
* 每列方框的数量
*/
var everyRowBoxQuantity:Int
Column (
modifier = Modifier
//可滚动
.verticalScroll(rememberScrollState())
){
BoxWithConstraints {
//获取Column最大宽度
districtWidth=maxWidth.value
//计算每列方框的数量
everyRowBoxQuantity=floor(districtWidth/gridBoxWidth).toInt()
//类别表
val categoryList:MutableList<String> = mutableListOf()
//显示列表,类别-数据列表
val gridList:MutableMap<String,List<TestData>> = mutableMapOf()
dataList.groupBy { it.category }.forEach { t, u ->
categoryList.add(t)
gridList.put(t,u)
}
Column {
for(i in gridList){
Text("种类"+i.key)
GridRow(everyRowBoxQuantity,i.value)
}
}
}
}
}
@Composable
fun GridRow(everyRowBoxQuantity:Int,rowList:List<TestData>){
var boxQuantity=everyRowBoxQuantity-1
//至少显示一行
if(boxQuantity<=0)boxQuantity=1
//分配每行box时计数
var i=1
//每行显示的内容
val everyRowList:MutableList<TestData> = mutableListOf()
for(it in rowList){
everyRowList.add(it)
//每行分配完成或最后一个元素时,显示Row
if(i%boxQuantity==0||it==rowList.last())
{
Row {
everyRowList.forEach {
GridBox(it)
}
}
everyRowList.clear()
}
i++
}
}
@Composable
fun GridBox(testData: TestData) {
var u:Color=Color.Black
//不同的状态显示不同的值
when(testData.state){
"0"->u= Color.Black
"1"->u= Color.Blue
"2"->u= Color.Green
}
Box(
modifier = Modifier
.padding(16.dp)
.width(200.dp)
.height(130.dp)
.background(u)
){
Column {
Text(testData.id.toString())
Text(testData.name)
}
}
}
}