我一直在深入研究 Jetpack Compose。在这里,我使用行、列和间隔符来构建此屏幕截图。有更适合我应该尝试的可组合项吗?
我无法让 LazyVerticalGrid 将水母放置在其位置。它想把它放在黑狗下方的左侧,这样会留下一个空白空间,并将棕色狗推到自己的线上。
我还尝试了Accompanist的FlowRow,它绘制了与LazyVerticalGrid相同的排列。也可能我对两者的 API 都不够熟悉。
后来我想学习拖放来重新排序项目。当我设置这个小部件以使生活更轻松时,是否需要考虑一些因素?在我看来,这些单独的行和列可能会妨碍我,但也许没有影响。
感谢您的任何见解!
Google jetpack 撰写路径有关于自定义布局的课程,但我认为您可以使用
Lazy Grid
,它可以轻松使用网格。
链接 Android 开发者 Lazy Grids 如果您单击
lazy vertical grid
链接,您将看到可以有多行带有 different modifiers and number of grid cells
的项目。
我很乐意给您一个有效的示例,所以我可能会很快编辑它。
我的此类网格的自定义布局的简单版本如下所示:
@Composable
fun GalleryScreen(
items: List<String>
) {
GalleryGrid(
modifier = Modifier.fillMaxWidth(),
contentPadding = PaddingValues(16.dp)
) {
items.forEach { url ->
AsyncImage(url = url)
}
}
}
@Composable
fun GalleryGrid(
modifier: Modifier = Modifier,
contentPadding: PaddingValues,
content: @Composable () -> Unit
) {
val scrollState = rememberScrollState()
Layout(
modifier = modifier.verticalScroll(state = scrollState),
measurePolicy = rememberMeasurePolicy(
contentPadding = contentPadding
),
content = content
)
}
@Composable
private fun rememberMeasurePolicy(
contentPadding: PaddingValues
): MeasurePolicy = remember(contentPadding) {
GalleryGridMeasurePolicy(contentPadding)
}
private class GalleryGridMeasurePolicy(
private val contentPadding: PaddingValues
) : MeasurePolicy {
override fun MeasureScope.measure(measurables: List<Measurable>, constraints: Constraints): MeasureResult {
val start = contentPadding.calculateLeftPadding(LayoutDirection.Ltr).roundToPx()
val top = contentPadding.calculateTopPadding().roundToPx()
val end = contentPadding.calculateRightPadding(LayoutDirection.Ltr).roundToPx()
val bottom = contentPadding.calculateBottomPadding().roundToPx()
val width = constraints.maxWidth
val itemWidth = (width - start - end) / GalleryGridDefaults.SpanCount
val firstItemWidth = itemWidth * GalleryGridDefaults.FirstItemSpanCount
var height = top
var rowHeight = 0
val itemHeight = (itemWidth / GalleryGridDefaults.AspectRatio).roundToInt()
val placeablesWithOffset = measurables
.take(GalleryGridDefaults.MaxPhotoCount)
.mapIndexed { index, measurable ->
when (index) {
// 1 row, 1 item
0 -> {
val firstItemHeight = itemHeight * GalleryGridDefaults.FirstItemSpanCount
rowHeight = firstItemHeight
height += rowHeight
measurable.measure(
Constraints(
minWidth = firstItemWidth,
maxWidth = firstItemWidth,
minHeight = firstItemHeight,
maxHeight = firstItemHeight
)
) to IntOffset(
x = start,
y = top
)
}
// 1 row, 2 item
1 -> {
measurable.measure(
Constraints(
minWidth = itemWidth,
maxWidth = itemWidth,
minHeight = itemHeight,
maxHeight = itemHeight
)
) to IntOffset(
x = start + firstItemWidth,
y = top
)
}
// 1 row, 3 item
2 -> {
measurable.measure(
Constraints(
minWidth = itemWidth,
maxWidth = itemWidth,
minHeight = itemHeight,
maxHeight = itemHeight
)
) to IntOffset(
x = start + firstItemWidth,
y = top + itemHeight
)
}
// others
else -> {
val column = index % GalleryGridDefaults.SpanCount
if (column == 0) {
rowHeight = itemHeight
height += rowHeight
}
measurable.measure(
Constraints(
minWidth = itemWidth,
maxWidth = itemWidth,
minHeight = itemHeight,
maxHeight = itemHeight
)
) to IntOffset(
x = start + column * itemWidth,
y = height - rowHeight
)
}
}
}
return layout(width, height + bottom) {
placeablesWithOffset.forEach { (placeable, offset) ->
placeable.place(offset)
}
}
}
}
private object GalleryGridDefaults {
const val SpanCount = 3
const val MaxPhotoCount = 9
val AspectRatio = 1f
const val FirstItemSpanCount = 2
}
Layout
,它允许测量和放置内容。 🤞🏽