考虑到我已经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相关问答推荐

Android:MethodHandle. invoke和MethodHandle. invokeExact仅从Android O( - min—api 26)开始支持

Jetpack编写Lazy列滑动删除动画不顺利结束

当我在Android上运行应用程序时,组件会随机调整大小和移动

推断的类型是片段,但应为上下文

无法将非静态方法与Frida挂钩

Android系统应用程序启用编程以太网网络共享

我正在创建一个简单的连接四个游戏,我需要一个弹出式窗口当你赢了

FireBase Android ChildEventListener在被规则拒绝时触发(RTDB)

我无法在底部导航栏中正确导航-Android底部导航视图

解决失败:Landroidx/compose/runtime/PrimitiveSnapshotStateKt

如何正确创建可拖动的浮动视图?

Android Jetpack Compose 电视焦点恢复

在单元测试下断言协程未完成

通过 adb 解压并重新安装后 Android 应用程序崩溃

如何添加到先前预填充的 Room 数据库?

在 Jetpack Compose 中重用具有重复代码的列

如何在 Android Studio 中创建新的可组合函数?

在alert 对话框生成器中启动协程

IconButton 中可绘制的图标是黑色的,尽管它是白色的

EAS 构建失败,错误代码为 1,但 Expo Build 成功,我需要 EAS 构建来删除未使用的包,如 com.segment.analytics.android:analytics