SwiftUI中,我们可以使用LazyVGridLazyHGrid视图创建一个二维响应列表。如果我们想要一个垂直网格,我们可以使用LazyVGrid视图,如果我们想要一个水平网格,可以使用LazyHGrid视图。这些视图允许我们创建一个网格的项目,以适应不同的方向和屏幕大小。

LazyVGrid和LazyHGrid

struct GridDemo: View {
  private var data  = Array(1...50)
  private var columns: [GridItem] = [
      GridItem(.fixed(50)),
      GridItem(.fixed(50)),
      GridItem(.fixed(50))
  ]

  var body: some View {
    ScrollView{
      LazyVGrid(columns: columns, spacing: 20) {
        ForEach(data, id: \.self) { item in
          Text(String(item))
            .frame(width: 50, height: 50, alignment: .center)
            .background(.blue)
            .cornerRadius(10)
            .foregroundColor(.white)
            .font(.title)
        }
      }
    } 
    .padding()
  }
}

在这里插入图片描述
在上面的例子中,我们使用LazyVGrid创建了一个显示50个Text的网格。首先,用GridItem定义了一些列。在这里,我们通过设置.fixed(50)定义了三个固定宽度为50的列。

然后,我们将网格视图放入滚动视图中,使其可滚动。最后,指定列作为LazyVGrid的参数。这就是我们在SwiftUI中创建网格布局所需要做的一切。

LazyVGrid:竖向滚动,按行从左向右加载每一项,从上往下加载每一行。每行的第一个项组成一列,依次向右为第二列,第三列等。
LazyHGrid:横向滚动,按列从上到下加载每一项,从左向右加载每一列。每列的第一个项组成一行,从上向下依次为第一行,第二行等。

GridItem

GridItem主要是对这种二维的网格布局的行或者列的一种描述。要想配置二维网格布局,我们需要创建一个包含GridItem实例的一个数组。每一个GridItem实例都描述了LazyVGrid中的一列或者LazyHGrid中的一行的sizespacingalignment信息。

初始化GridItem的方法如下:

init(
    _ size: GridItem.Size = .flexible(),
    spacing: CGFloat? = nil,
    alignment: Alignment? = nil
)

GridItem Size

其中GridItem.Size是一个枚举,有三种类型:

/// 这种类型将一个或多个项目放入到单个灵活的空间中,使用提供的边界和间距来
/// 确定适合多少项。这种方法倾向于尽可能多地插入最小大小的项,但让它们增加到最大大小。
case adaptive(minimum: CGFloat, maximum: CGFloat)
/// 这种类型指定了固定的值用于列的宽度或者行的高度。
case fixed(CGFloat)
/// 这种类型的大小是删除间隔和非灵活项后的网格大小,除以固定在提供边界内的灵活项的数量。
case flexible(minimum: CGFloat, maximum: CGFloat)

说起来还是不太好理解。

比如说我们想在LazyVGrid的一行或者LazyHGrid的一列显示尽可能多的item,我们可以用adaptive(),比如设置GridItem(.adaptive(minimum: 50)) ,那么就会以最小50的距离尽可能的排列更多的item。

LazyVGrid
在这里插入图片描述

LazyHGrid
在这里插入图片描述

如果要控制每列或行中的数量,可以使用flexible()。但是,如果没有足够的空间容纳视图的最小尺寸,则每项之间可能会重叠。

LazyVGrid
在这里插入图片描述

LazyHGrid
在这里插入图片描述

如果就像给列或者行设置一个固定的尺寸,可以使用fixed()

LazyVGrid
在这里插入图片描述

LazyHGrid
在这里插入图片描述

GridItem Spacing

Spacing定义了当前项与下一项的间距。如果此值为nil,则该项使用当前平台的合理默认值。

下面是一个五列网格的示例,其中列中每个项目之间的间距分别为0、10、20、30、40。

struct GridDemo: View {
  private var data  = Array(1...50)
  private var columns: [GridItem] = [
    GridItem(.fixed(50), spacing: 0),
    GridItem(.fixed(50), spacing: 10),
    GridItem(.fixed(50), spacing: 20),
    GridItem(.fixed(50), spacing: 30),
    GridItem(.fixed(50), spacing: 40)
  ]

  var body: some View {
    ScrollView() {
      LazyVGrid(columns: columns) {
        ForEach(data, id: \.self) { item in
          Text(String(item))
            .frame(width: 50, height: 50, alignment: .center)
            .background(.blue)
            .cornerRadius(10)
            .foregroundColor(.white)
            .font(.title)
        }
      }
    } 
    .padding()
  }
}

在这里插入图片描述
这里需要注意的是最后一列定义的spacing是40,但是因为这个是最后一列,所以这个40就被忽略了。

在看一下采用LazyHGrid的效果:

struct GridDemo: View {
  private var data  = Array(1...50)
  private var columns: [GridItem] = [
    GridItem(.fixed(50), spacing: 0),
    GridItem(.fixed(50), spacing: 10),
    GridItem(.fixed(50), spacing: 20),
    GridItem(.fixed(50), spacing: 30),
    GridItem(.fixed(50), spacing: 40)
  ]

  var body: some View {
    ScrollView(.horizontal) {
      LazyHGrid(rows: columns) {
        ForEach(data, id: \.self) { item in
          Text(String(item))
            .frame(width: 50, height: 50, alignment: .center)
            .background(.blue)
            .cornerRadius(10)
            .foregroundColor(.white)
            .font(.title)
        }
      }
    } 
    .padding()
  }
}

在这里插入图片描述

GridItem Alignment

放置每个视图时使用的对齐方式。使用此属性将视图的相对位置锚定到视图分配的网格空间中的相对位置。

默认情况下,每个项目将在行/列内居中对齐。我们可以通过alignment属性来改变这个。
在这里插入图片描述

写在最后

文章中主要介绍了LazyVGridLazyHGrid的主要用法,包括布局类型,间距和对齐等属性的设置,希望能够让大家更直观的了解LazyVGridLazyHGrid的使用,下一篇文章我们一起看一下iOS 16新推出的GridGridRow的用法。

最后,希望能够帮助到有需要的朋友,如果您觉得有帮助,还望点个赞,添加个关注,笔者也会不断地努力,写出更多更好用的文章。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐