[Swift]让我们考虑一下SwiftUI的LazyVGrid / LazyHGrid


*注意
-已经确认可以在Xcode 12 beta环境中使用。该行为可能会在正式版本中更改。
-基于同样的想法,即撰写Swift和iOS 8违反了NDA,我认为可以附加Apple发布的图像/视频代码及其扩展代码。
-本文中的屏幕截图均在Xcode 11.5和iOS 13上复制。 (没有Xcode12 beta和iOS14)

介绍

第一次是WWDC2020,我想有很多人并不兴奋。
Xcode12 Beta的发行也已经开始,并且在官方网站上一次扩展了各种API参考。

Swift UI在上一届WWDC 2019上引起了人们的注意,但是仍然存在许多问题,并且对该更新的期望很高。 ..
似乎已经在此公告中添加了许多API!

其中,我专注于LazyVGrid / LazyHGrid。

LazyVGrid / LazyHGrid

尽管它是在WWDC2020的视频中发布的,但现在可以在SwiftUI上轻松创建网格设计,如下所示。

grid example

(引用:WWDC2020-SwiftUI的新功能/ 10:11?)

1.文档

首先,让我们看一下官方文档。

スクリーンショット 2020-06-24 17.15.39 2.png

(引用:文档--LazyVGrid)

顾名思义,有一种机制可以在垂直和水平方向上构建网格。
另外,该部分

每个部分的描述都相同

网格是"惰性的",因为网格视图在需要它们之前不会创建项目。

似乎直到需要时才生成View。
稍后将对此进行说明。

2.代码示例

首先,我认为看一个简单的例子最容易。
这次我用LazyVGrid创建了一个示例。
(*屏幕截图是与Xcode 11.5相同的屏幕的再现)

スクリーンショット 2020-06-24 15.18.10.png

  • 与Xcode 11.5再现同一屏幕的代码
1
2
3
4
5
6
7
8
9
10
ScrollView {
    ForEach((0...24), id: \.self) { row in
        HStack {
            ForEach((1...4), id: \.self) { column in
                Text("\(row*4+column)")
                    .frame(width: 80, height: 60) // widthは目視で同じになるように任意の値を設定
            }
        }.frame(maxWidth: .infinity)
    }
}
  • 使用LazyVGrid的代码
1
2
3
4
5
6
7
8
ScrollView {
    LazyVGrid(columns: Array(repeating: GridItem(), count: 4)) { // カラム数の指定
        ForEach((1...100), id: \.self) { index in
            Text("\(index)")
                .frame(width: 60, height: 60)
        }
    }
}

生成的列与

列中的GridItem一样多。

以前,必须使用ForEachStack通过嵌套要复制的网格部分来配置屏幕。
使用LazyVGrid,它将被指定的列数分隔,并且代码将更加简洁明了,不是吗?

3. GridItem

文档

如上面的代码中所述,要使用LazyVGrid / LazyHGrid配置屏幕,必须传递GridItem

スクリーンショット 2020-06-24 17.56.19.png

(引用:文档--GridItem)

属性可以看到,它用于调整布局。
作为图像,我认为它接近UICollectionView的Layout。

变量

通过使用此GridItem,可以创建可变网格。
通过在生成GridItem时将GridItem.Size指定为参数是可能的。
您还可以在此处设置最小和最大尺寸。

スクリーンショット 2020-06-24 19.49.24.png

  • Quote:文档--GridItem.Size

基本上使用上述三种类型。

1
2
3
① fixed    : グリッドのサイズを固定で設定
② flexible : グリッドのサイズを最小値?最大値で設定
③ adaptive : グリッドのサイズを最小値?最大値で設定し、アイテムを詰めて設置

这将是

让我们来看每个示例。

①固定

(*屏幕截图是与Xcode 11.5相同的屏幕的再现)

スクリーンショット 2020-06-24 20.43.17.png

<详细信息> <摘要>单击此处,获取与Xcode 11.5几乎相同的屏幕的代码

1
2
3
4
5
6
7
8
9
ScrollView {
    ForEach((0...24), id: \.self) { row in
        HStack {
            Text("\(row*4)").frame(width: 10, height: 60)
            Text("\(row*4+1)").frame(width: 30, height: 60)
            Text("\(row*4+2)").frame(width: 20, height: 60)
        }.frame(maxWidth: .infinity)
    }
}

1
2
3
4
5
6
7
ScrollView {
    LazyVGrid(columns: [GridItem(.fixed(10)), GridItem(.fixed(30)), GridItem(.fixed(20))]) { // GridItemが3つなので3カラム
        ForEach((1...100), id: \.self) { index in
            Text("\(index)")
        }
    }
}

可以为每列设置一个固定值。

②灵活

"①固定"是可变形式。

1
2
3
4
5
6
7
ScrollView {
    LazyVGrid(columns: [GridItem(.flexible(minimum: 30, maximum: 100)), GridItem(.flexible(minimum: 0, maximum: 10))]) { // GridItemが2つなので2カラム
        ForEach((1...100), id: \.self) { index in
            Text("\(index)")
        }
    }
}

可以为每列设置最小值和最大值。

③自适应

*这是现有的,无法复制,因此我将附上我可以做的图像。
Quote:实现一种布局,其中标签在UICollectionView

中左对齐

スクリーンショット 2020-06-24 20.43.17.png

1
2
3
4
5
6
7
ScrollView {
    LazyVGrid(columns: [GridItem(.adaptive(minimum: 100, maximum: 200))]) {
        ForEach((1...100), id: \.self) { index in
            Text("\(index)")
        }
    }
}

设置为1,将包装和显示设定的最小值和最大值。
设置多个adaptive时,操作系统方面似乎对其进行了很好的划分(我尝试了几次,但是就是那样)

4.懒惰

" 1.文档"

中未对此部分进行说明

网格是"惰性的",因为网格视图在需要它们之前不会创建项目。

此视图对于Lazy非常有意义。
这意味着屏幕呼叫的时间是不同的。

我想将以下代码添加到新旧的Swift UI代码中,并检查行为上的区别。

1
2
3
4
5
6
.onAppear {
    debugPrint("onAppear: \(/* current index */)")
}
.onDisappear {
    debugPrint("onDisappear: \(/* current index */)")
}

在显示/隐藏屏幕时,使用

onAppear / onDisappear输出日志。

获取与Xcode 11.5

再现同一屏幕的代码的日志

スクリーンショット 2020-06-24 18.08.50.png

到目前为止,就网格实现而言,所有索引都是在生成屏幕的同时获取的。
换句话说,所有屏幕(文本)都会随着屏幕生成而被调用。

使用LazyVGrid

获取代码日志

与现有列表相同。
换句话说,onAppear在项目显示时触发,onDisappear在项目隐藏时触发。

スクリーンショット 2020-06-24 18.33.23.png

(图像是图像。来自Xcode 11.5)

在实际开发中,我认为将列出大量复杂的视图。
因此,旧的实现方式不利于性能,不适合实际战斗。
在那部分中,似乎可以使用Grid来提高性能。

5. PinnedScrollableViews

我觉得我无法用名字来想象,但是
Section header?一个属性,用于指定是否修复节的页脚。

スクリーンショット 2020-06-24 17.50.13.png

(引用:文档--PinnedScrollableViews)

我准备了一个固定的标头作为试用版。
(*屏幕截图是与Xcode 11.5相同的屏幕的再现)

スクリーンショット 2020-06-24 19.17.37 2.png

1
2
3
4
5
6
7
8
9
10
ScrollView {
    LazyVGrid(columns: Array(repeating: GridItem(), count: 4), pinnedViews: .sectionHeaders) { // 固定する方を指定
        Section(header: Text("header")) { // セクション
            ForEach((1...100), id: \.self) { index in
                Text("\(index)")
                    .frame(width: 60, height: 60)
            }
        }
    }
}

只需将其添加到

参数中,就非常容易。
作为图像,我认为它接近UICollectionElementKindSection Header/Footer
如果不指定此参数,则该部分将按原样滚动。

在最后

到目前为止,在Swift UI中还没有等效的UICollectionView,因此我不得不在开发过程中以骇人的方式进行大量工作。
这次重点关注的电网能否完全弥补这一点值得怀疑。 .. ..

自WWDC2020宣布以来,由于SwiftUI的许多API的增加,开发范围已扩大。
考虑到某些功能只能使用SwiftUI开发,因此在最近几年中似乎必须过渡到SwiftUI。

可能有错误,请指出mm

其他

存储库
--SwiftUI_LazyGrid

文件
-文档--LazyHGrid
-文档--LazyVGrid
-文档--GridItem
-文档--GridItem.Size

外国人的视频,解释了网格的布局
-在iOS的SwiftUI 2.0中构建网格14