【问题标题】:How to create GridView using Jetpack Compose如何使用 Jetpack Compose 创建 GridView
【发布时间】:2020-02-24 01:12:47
【问题描述】:

如何在Jetpack compose中创建Gridview而不使用recycler view或android.widget.gridview?

【问题讨论】:

  • @Gabriele Matiotti,我的意思是如何在不使用 android.widget.GridView 的情况下创建网格视图,我已经编辑了我的帖子
  • 自 Compose 版本 1.0.0-alpha09 以来,有一个标准组件:LazyVerticalGrid

标签: android android-jetpack-compose android-jetpack-compose-list


【解决方案1】:

使用1.0.xLazyVerticalGrid 可组合组件为在网格中显示项目提供实验性支持

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

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

cells = GridCells.Fixed(4) 表示有 4 列 1/4 的父级宽度。

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

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

cells = GridCells.Adaptive(minSize = 64.dp) 意味着将有尽可能多的列,每列至少为 64.dp,并且所有列的宽度都相同。

【讨论】:

【解决方案2】:

UPD:Compose 版本 1.0.0-alpha09 引入了标准组件:

LazyVerticalGrid

另一个基于 LazyColumnFor 的解决方案(Jetpack Compose 版本 1.0.0-alpha04)

@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)
    }
}

【讨论】:

    【解决方案3】:

    正如@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))
            }
        }
    

    【讨论】:

      【解决方案4】:

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

      预览

      代码

      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))
                  }
                  ...
              }
      

      完整代码为here

      我决定实现我自己的自适应网格布局,因为现有的 LazyVerticalGrid 是实验性的,将来可以删除,要使用它,你必须用 @ExperimentalFoundationApi 递归地注释使用它的堆肥:

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

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

      【讨论】:

        【解决方案5】:

        更新@Pavel Marchenko 的答案,因为一些 compose 函数的名称发生了变化: 需要 LazyColumn() 而不是 LazyColumnFor() 并使用 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)
                  }
                }
              }
            }
          }
        }
        

        【讨论】:

        • 这将导致 paging3 无法加载
        【解决方案6】:

        我已经为使用 android jetpack compose 创建了一个自定义 gridview,直到他们不支持 Compose 中 Gridlayout 的官方 recycleview。

        @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) {
        ....
        }
        

        【讨论】:

          【解决方案7】:

          对@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)
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-05-23
            • 2022-08-22
            • 1970-01-01
            • 1970-01-01
            • 2021-08-12
            • 1970-01-01
            相关资源
            最近更新 更多