android 如何使用Jetpack合成创建GridView

zlhcx6iw  于 2023-04-04  发布在  Android
关注(0)|答案(9)|浏览(128)

如何在Jetpack compose中创建Gridview而不使用回收器视图或android.widget.gridview?

oxalkeyp

oxalkeyp1#

通过1.x.yLazyVerticalGrid组合工具为在网格中显示项目提供了实验支持

val numbers = (0..20).toList()

LazyVerticalGrid(
    columns = GridCells.Fixed(4)
) {
    items(numbers.size) {
        Column(horizontalAlignment = Alignment.CenterHorizontally) {
            Text(text = "Number")
            Text(text = "  $it",)
        }
    }
}

columns = GridCells.Fixed(4)意味着有4列,是父列宽度的1/4。

val numbers = (0..20).toList()

LazyVerticalGrid(
    columns = GridCells.Adaptive(minSize = 64.dp)
) {
    items(numbers) {
        Column(horizontalAlignment = Alignment.CenterHorizontally) {
            Text(text = "Number")
            Text(text = "  $it",)
        }
    }
}

columns = GridCells.Adaptive(minSize = 64.dp)将意味着将存在尽可能多的列,并且每一列将至少为64.dp,并且所有列将具有相等的宽度。

uwopmtnx

uwopmtnx2#

UPD:Compose版本1.0.0-alpha 09引入标准组件:

惰性垂直网格
另一种基于LazyColumn的解决方案(Jetpack Compose版本1.0.0-alpha 04)

@Composable
fun <T> LazyGridFor(
    items: List<T>,
    rowSize: Int = 1,
    itemContent: @Composable BoxScope.(T) -> Unit,
) {
    val rows = items.chunked(rowSize)
    LazyColumnFor(rows) { row ->
        Row(Modifier.fillParentMaxWidth()) {
            for ((index, item) in row.withIndex()) {
                Box(Modifier.fillMaxWidth(1f / (rowSize - index))) {
                    itemContent(item)
                }
            }
        }
    }
}
    
@Preview("LazyGridFor: example")
@Composable()
fun LazyGridForPreview() {
    val data = (1..100).map(Integer::toString)
    LazyGridFor(data, 3) { item ->
        Text(item)
    }
}
unguejic

unguejic3#

正如@Pavel Marchenko提到的,LazyVerticalGrid是从1.0.0-alpha09版本添加的
下面是一个简单的例子:

LazyVerticalGrid(
        cells = GridCells.Adaptive(96.dp),
        contentPadding = PaddingValues(16.dp),
    ) {
        items(bookList) { book ->
            Image(book.cover, modifier = Modifier.padding(8.dp))
        }
    }
gywdnpxw

gywdnpxw4#

我创建了一个自适应网格布局:

上一页

代码
LazyColumn(modifier = modifier) {
            ...
            val numberOfItemsByRow = LocalConfiguration.current.screenWidthDp / 200 // you can replace 200 by the minimum size you want your cells to have.

            items(items = trendingGameList.chunked(numberOfItemsByRow)) { rowItems ->
                Row(
                    horizontalArrangement = Arrangement.spacedBy(14.dp),
                    modifier = Modifier.padding(horizontal = 16.dp),
                ) {
                    for (game in rowItems) {
                        GameCard(game = game, onClick = { }, modifier = Modifier.weight(1F))
                    }
                }
                Spacer(Modifier.height(14.dp))
            }
            ...
        }

完整的代码在这里。
我决定实现我自己的自适应网格布局,因为现有的LazyVerticalGrid是实验性的,将来可以删除,要使用它,你必须递归地注解使用它的compostable:

@ExperimentalFoundationApi 
@Composable
fun A {
    LazyVerticalGrid {
        ...
    }
}

@ExperimentalFoundationApi 
@Composable
fun B {
 A {..}
}

@ExperimentalFoundationApi 
@Composable
fun C {
 B {..}
}
...

使用需要-Xopt-in=kotlin.RequiresOptIn编译器参数的@OptIn(ExperimentalFoundationApi::class)

lsmd5eda

lsmd5eda5#

更新@Pavel Marchenko的答案,因为一些compose函数的名称发生了变化:需要使用LazyColumn()代替LazyColumn()并使用items()函数:

@Composable
fun <T> LazyGridFor(
  items: List<T>,
  rowSize: Int = 1,
  itemContent: @Composable BoxScope.(T) -> Unit,
) {
  LazyColumn {
    items(items = items.chunked(rowSize)) { row ->
      Row(Modifier.fillParentMaxWidth()) {
        for ((index, item) in row.withIndex()) {
          Box(Modifier.fillMaxWidth(1f / (rowSize - index))) {
            itemContent(item)
          }
        }
      }
    }
  }
}
pgx2nnw8

pgx2nnw86#

我已经创建了一个自定义的gridview使用android jetpack撰写,直到他们将不支持官方recycleview的Gridlayout在撰写。

@Composable
fun <T> GridView(
cols: Int = 0,
list: List<T>,
child: @Composable() (dataModal: T) -> Unit
) {

val rows = (list.size / cols) + (if (list.size % cols > 0) 1 else 0)
VerticalScroller(modifier = 
Modifier.fillMaxHeight().fillMaxHeight().drawBackground(color = colorResource(
    id = R.color.color_bg_application
))) {
    Table(columns = cols) {
        for (r in 0 until rows) {
            tableRow {
                for (c in 0 until cols) {
                    //Cell
                    val i = (r * cols) + c
                    if (i < list.size) {
                        child(list[i])
                    } else {
                        break
                    }
                }
            }
        }

    }
}
}

用途

GridView(cols = 4, list = model.list,child = { Item( it) })

项目声明

@Composable
fun Item(t: T) {
....
}
lskq00tm

lskq00tm7#

由于LazyVerticalGrid不能在LazyColumn中使用,因此不能在可滚动页面中使用它。我在compose中创建了一个自定义LazyGrid实现库。它是懒惰的,所以它的性能非常好。对于不同的场景有不同的项目放置类型,并且非常容易用途:

LazyColumn {
    item {
        Text(text = "Title")
    }
    LazyGrid(
        rows = listOf(),
        elementPerRow = 4,
        itemPlacementType = ItemPlacementType.FixedSize(itemWidth = 80.dp),
        contentPadding = PaddingValues(horizontal = 16.dp)
    ) { item, modifier ->
        CustomGridItem(item, modifier, onClick = { /* if needed */ })
    }
}

还有一个可折叠的版本。更多信息,文档,源代码和演示可以在以下位置找到:https://github.com/yusufarisoy/lazy-grid

dependencies {
    implementation 'com.github.yusufarisoy:lazy-grid:1.0.0'
}

它也是可重启和可跳过的,以使compose编译器以最佳性能工作。https://chris.banes.dev/composable-metrics/

n1bvdmb6

n1bvdmb68#

对@Madhav的答案做了一些修改(使用compose v1.0.0-alpha01):

@Composable
fun <T> GridView(
        cols: Int = 1,
        list: List<T>,
        rowModifier: Modifier = Modifier,
        colModifier: Modifier = Modifier,
        child: @Composable (dataModal: T) -> Unit
) {

    val rows = (list.size / cols) + (if (list.size % cols > 0) 1 else 0)
    
    ScrollableColumn(modifier = colModifier) {
        
        for (r in 0 until rows) {
            Row(modifier = rowModifier, horizontalArrangement = Arrangement.SpaceAround) {
                for (cell in 0 until cols) {
                    val i = (r * cols) + cell
                    if (i < list.size) { child(list[i]) } else { break }
                }
            }
        }
    }

}

用途

GridView(cols = 2, list = listOf("1", "2", "3", "4",)) {
     Text(text = it)
}
lp0sw83n

lp0sw83n9#

LazyVerticalGrid使用滚动状态,从而使其在LazyColum中无用
这里的实现只使用行和列

sealed class GridCells {

abstract val columns: Int

data class Fixed(val count: Int) : GridCells() {
    override val columns: Int = count
}

object Adaptive : GridCells() {
    override val columns: Int = 1
}}

@Composable
fun VerticalGrid(
    modifier: Modifier = Modifier,
    gridCells: GridCells,
    totalItems: Int,
    contentPadding: PaddingValues = PaddingValues(0.dp),
    content: @Composable (Int) -> Unit,
) {
Column(modifier = modifier) {
    val columnCount = when (gridCells) {
        is GridCells.Fixed -> gridCells.columns
        is GridCells.Adaptive -> ceil(sqrt(totalItems.toDouble())).toInt()
    }

    val rowCount = ceil(totalItems.toDouble()/columnCount).toInt()

    for(i in 0 until rowCount){
        Row(Modifier.fillMaxWidth()) {
            for (j in 0 until columnCount) {
                val index = j + i * columnCount
                Box(
                    Modifier
                        .weight(1f)
                        .padding(contentPadding)
                ) {
                    if (index < totalItems) {
                        content(index)
                    }
                }
            }
        }
    }
}

}

相关问题