Android记录--compose中设置宽度百分比或者自己计算

9 阅读2分钟

需求:在Row或者column中,设置某个组件的宽度或者高度为百分比。

常规方式

使用fillMaxWidth(0.3f)的方式设置宽度为可用宽度的30%

使用weight的方式设置权重,间接设置百分比宽高

遇到的问题

我在一个Row中,设置ABC三个组件的宽度都是fillMaxWidth(0.3f),效果并不像想象中的,每个组件的宽度都相同

测试:

Row(modifier = Modifier.width(100.dp).background(Color.Red)) {
    Text("A", modifier = Modifier.fillMaxWidth(0.5f).background(Color.Blue))
    Text("B", modifier = Modifier.fillMaxWidth(0.5f).background(Color.Yellow))
    Text("C", modifier = Modifier.fillMaxWidth(0.5f).background(Color.Green))
}

效果如下:

image.png

看到A是占了总宽度的一半,B是占了剩余宽度的一半,C又是占了计算后剩余宽度的一半

得出结论,在Row容器中,Modifier.fillMaxWidth(0.5f)是设置宽度为可用宽度的一半

吐槽:使用ai得出的结论都是错误的:

image.png

使用Widget的方式设置时需要注意。使用Spacer

常见的情况下,一个组件在设置Modifier的第一项为padding的时候,表现是我们以前的Margin效果

但是,使用weight的时候,要注意这一点。 比如一个Row中,三个组件,都设置weight为1,表示它们三个平分可用空间

这时候就要注意,比如想为某个组件通过padding的方式设置margin,那么就会出现错误效果,比如

Row(modifier = Modifier.width(300.dp).height(50.dp).background(Color.Gray)) {
    Text(text = "111", modifier = Modifier.weight(1f).background(Color.Red))
    Text(text = "111", modifier = Modifier.padding(start = 40.dp).weight(1f).background(Color.Blue))
    Text(text = "111", modifier = Modifier.weight(1f).background(Color.Magenta))
}

image.png

明显,设置的padding也算在组件的尺寸中了

这时候就要使用Spacer来设置margin了

Column(modifier = Modifier.fillMaxWidth().fillMaxHeight().padding(top = 50.dp)) {
    Row(modifier = Modifier.width(300.dp).height(50.dp).background(Color.Gray)) {
        Text(text = "111", modifier = Modifier.weight(1f).background(Color.Red))
        Spacer(modifier = Modifier.width(40.dp))
        Text(text = "111", modifier = Modifier.weight(1f).background(Color.Blue))
        Text(text = "111", modifier = Modifier.weight(1f).background(Color.Magenta))
    }
}

image.png

这样才是平分可用空间。

自己计算,使用固定尺寸

比如我有一个可用空间,但是不知道它的实际尺寸,我想在内部设置一些组件,设置宽高为它的30%。如何实现?

获取可用空间的宽高

使用Modifier.onGloballyPosition函数,获取组件的尺寸,位置的相关信息

计算需要的尺寸,设置到对应的组件上

// 观察尺寸变化
var layoutWidth by remember {
    mutableIntStateOf(0)
}
var layoutHeight by remember {
    mutableIntStateOf(0)
}
// 进行尺寸转换和计算
val density = LocalDensity.current
val itemHeight = with(density) {
    (layoutHeight.toDp() - 20.dp) / 3
}

LazyVerticalGrid(
    columns = GridCells.Fixed(2),
    verticalArrangement = Arrangement.spacedBy(10.dp),
    horizontalArrangement = Arrangement.spacedBy(10.dp),
    modifier = modifier
        .fillMaxSize()
        .onGloballyPositioned { coordinates ->  // 获取当前组件尺寸
            val size = coordinates.size
            layoutWidth = size.width
            layoutHeight = size.height
        },
) {
    itemsIndexed(tipsList) { index, item ->
        Text(
            text = item,
            textAlign = TextAlign.Center,
            color = Color.White,
            fontSize = 30.sp,
            fontWeight = FontWeight.Bold,
            modifier = Modifier
                .fillMaxWidth()
                .height(itemHeight)
                .clip(shape = RoundedCornerShape(5.dp))
                .background(
                    color = if (index == 2) colorResource(R.color.orange) else colorResource(
                        R.color.teal_700
                    )
                )
                .wrapContentHeight(align = Alignment.CenterVertically)
        )
    }
}

这样,我设置的item的高度就是组件总高度-20dp后的三分之一