考虑到我已经try 使用像LazyVerticalGrid.Modifier.ill MaxHeight()和Fill MaxSize()这样的修饰符,但没有达到预期的结果,我如何确保Jetpack Compose主导航视图中的IconList在Scaffold组件中使用时占据整个屏幕?

编辑:

根据@Ethan Wu的建议对我的代码进行了一些更改,密度不考虑与topbar一起应用填充

@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@Preview
@Composable
fun HomeScreenPrev() {
    TotalApplicationTheme {
        val functionalities = listOf(
            Functionality("Search", "Search functionality", Icons.Default.ShoppingCart),
            Functionality("Settings", "Settings functionality", Icons.Filled.Face),
            Functionality("Like", "Like functionality", Icons.Default.ThumbUp),
            Functionality("Warning", "Warning functionality", Icons.Default.Warning),
            Functionality("Search", "Search functionality", Icons.Default.Search),
            Functionality("Settings", "Settings functionality", Icons.Default.Settings),
        )
        HomeScreen(functionalities = functionalities)
    }
}

@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@Composable
fun HomeScreen(functionalities: List<Functionality>) {
    Scaffold(
        topBar = { MainTopBar() },
    ) { ActionPanel(functionalities = functionalities, modifier = Modifier.padding(it)) }
}

@Composable
fun ActionPanel(functionalities: List<Functionality>, modifier: Modifier) {
    val density = LocalDensity.current
    with(density) {
        val eachHeight =
            (LocalConfiguration.current.screenHeightDp) * density.density / (functionalities.size / 2)
        LazyVerticalGrid(
            modifier = modifier, columns = GridCells.Fixed(2)
        ) {
            items(functionalities) {
                TaskCard(it, modifier = Modifier.height(eachHeight.toDp()))
            }
        }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TaskCard(functionality: Functionality, modifier: Modifier = Modifier) {
    Card(modifier = modifier,
        shape = RectangleShape,
        border = BorderStroke(1.dp, Color.LightGray),
        colors = CardDefaults.cardColors(
            containerColor = MaterialTheme.colorScheme.tertiary, //Card background color
            contentColor = Color.Black  //Card content color,e.g.text
        ),
        onClick = {
            /*TODO*/
        }) {

        Column(
            modifier = Modifier
                .padding(8.dp)
                .fillMaxWidth()
        ) {
            Spacer(modifier = Modifier.height(8.dp))
            Icon(
                imageVector = functionality.icon,
                contentDescription = null,
                modifier = Modifier
                    .size(48.dp)
                    .align(Alignment.CenterHorizontally)
            )
            Spacer(modifier = Modifier.height(8.dp))
            Text(text = functionality.name, style = MaterialTheme.typography.titleSmall)
            Spacer(modifier = Modifier.height(4.dp))
            Text(text = functionality.description, style = MaterialTheme.typography.bodyMedium)
        }
    }
}

当前结果

Current Screen with cards

推荐答案

您可以使用"布局判断器"来了解布局是什么样子的.

安卓开发者提供的这guide美元将是有帮助的.

但是,您可能会发现,您应该设置网格的每一行的高度才能达到您想要的效果.

为此,您可以try 获取当前布局高度,并将其除以列数,然后将每个项目的高度设置为该值.

val density = LocalDensity.current
with(density){
    val h = LocalConfiguration.current.screenHeightDp*density.density/(listItem.size/numberOfColumns)
    LazyVerticalGrid(
    ...
    ){
        items(...){
            Box(
                modifier = Modifier
                          .fillMaxWidth()
                          .height(h.toDp())
            ){
                ...
             }
        }
    }
}

结果会是这样的:

enter image description here

编辑:

下面是一个例子:

val density = LocalDensity.current
Test2Theme {
    // A surface container using the 'background' color from the theme
    Scaffold(modifier = Modifier.fillMaxSize()) {
        val listItem = listOf("1", "2", "3", "4", "5", "6")
        val numberOfColumns = 2
        with(density) {
            val eachHeight =
                LocalConfiguration.current.screenHeightDp*density.density/(listItem.size/numberOfColumns)
            LazyVerticalGrid(
                columns = GridCells.Fixed(numberOfColumns),
                modifier = Modifier
                    .padding(it)
                    .fillMaxSize()
            ) {
                items(listItem) {
                    Box(
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(eachHeight.toDp())
                            .border(
                                BorderStroke(1.dp, Color.Black)
                            )
                    ) {
                        Text(
                            text = it,
                            textAlign = TextAlign.Center,
                            modifier = Modifier.fillMaxSize()
                        )
                    }
                }
            }
        }
    }
}

不同分辨率结果

enter image description here

enter image description here

编辑:

上面的方法只适用于全屏. 如果您想要获取组件大小,Modifier.onGloballyPosited会在合成后传递该大小.

因此,要实现您的目标,应该是:

val listItem = listOf("1", "2", "3", "4", "5", "6")
val numberOfColumns = 2
var eachHeight by remember {
    mutableStateOf(0.dp)
}
LazyVerticalGrid(
    columns = GridCells.Fixed(numberOfColumns),
    modifier = Modifier
        .padding(it)
        .fillMaxSize()
        .onGloballyPositioned {
            eachHeight =
                with(density) { (it.size.height / (listItem.size / numberOfColumns)).toDp() }
        }
) {
    items(listItem) {
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .height(eachHeight)
                .border(
                    BorderStroke(1.dp, Color.Black)
                )
        ) {
            ...
        }
    }
}

结果会是这样的:

enter image description here

或者,您可以创建自定义布局,如

@Composable
fun MyGridLayout(
modifier: Modifier = Modifier,
row: Int,
col: Int,
content: @Composable ()-> Unit,
){
Layout(
    content = content,
    modifier = modifier
) { measurables, constraints ->
    //calculate each children's width & height
    var placeable = measurables.map {
        val width = constraints.maxWidth/col
        val height = constraints.maxHeight/row
        var c = Constraints(minWidth = width, maxWidth = width, maxHeight = height, minHeight = height)
        it.measure(c)
    }
    //then place them
    layout(constraints.maxWidth, constraints.maxHeight) {
        var yPosition = 0
        var xPosition = 0
        var mCol = 1
        placeable.forEach {
            it.placeRelative(xPosition, yPosition)
            if (mCol % col != 0) {
                xPosition += it.width
            }
            else {
                xPosition = 0
                yPosition += it.height
            }
            mCol+=1
        }
    }
}

然后用它来

Scaffold(
    modifier = Modifier.fillMaxSize(),
    topBar = {
        TopAppBar(
            ...
        )
    }
) {
    val listItem = listOf("1", "2", "3", "4", "5", "6")
    val numberOfColumns = 2
    MyGridLayout(
        modifier = Modifier.padding(it).fillMaxSize(),
        row = listItem.size/numberOfColumns,
        col = numberOfColumns
    ){
        listItem.forEach { str->
            Box(
                modifier = Modifier
                    .border(
                        BorderStroke(1.dp, Color.Black)
                    )
            ) {
              ...
            }
        }
    }
}

这两个结果是相同的.

Android相关问答推荐

使用Kotlin/Compose与Java/XML指南的比较

在带有REACT-Native-CLI的开发和生产中使用Firebase的最佳实践

Android App Google AdMob";广告加载失败:3;带有测试ID,&q;广告加载失败:1 for My Gahad

如何将.txtassets资源 转换为ArrayList<;字符串>;kotlin格式?

如何将 Room Persistence 依赖项正确添加到我的 Jetack Compose Android 应用程序

SQLite Kotlin 问题 - 没有数据库

@Immutable 对数据类有什么好处?

如何在一个活动中预加载图像然后在另一个活动中加载它们?

Android apk 不工作

为卡片的上半部分添加一个边框,用圆角半径组合

在 Jetpack Compose 中自动滚动后面的项目

单击 Jetpack Compose(单选)时,我无法为列表中的单个文本着色

自定义 Recyclerview [Android & Kotlin]

firebase-messaging和firebase-inappmessaging-display之间有什么区别?

Jetpack 使用 Canvas 组成半圆

如果我在网络请求中指定它们是否与判断网络功能相关

基线配置文件 x R8/Proguard

如何获取 Material Design 3 的底部导航栏高度?

如何增加 BottomSheetDialog 的高度以跟随垂直平移

创建后文件不存在