SwiftUI 简明教程之格子
本文为 eul 样章,如果您喜欢,请移步 [apuipstore/euui() 查看更多内容。
eul 是一款 swiftui & combine 教程 app(ios、macos),以文章(文字、图片、代码)配合真机示例(xcode 12+、ios 14+,macos 11+)的形式呈现给读者。笔者意在尽可能使用简洁明了的语言阐述 swiftui & combine 相关的知识,使读者能快速掌握并在 ios 开发中实践。
stack 相关的内容较为简单,这里不做讲解,这一节我们一起来熟悉 swiftui 中的 lazyhgrid 和 lazyvgrid。
griditem
lazyhgrid 和 lazyvgrid 可以快速构建类似 collectionview 的视图,其核心要点就是通过 griditem 进行动态布局。
每一个 griditem 实例都对应格子视图中的某一行或列,并为之配置对齐方式 alignment
、与下一个 griditem 实例的间距 spacing
,以及尺寸 size
。
注意:
size
在 lazyhstack 中约束的是每个 item 的高度,其宽度默认是自适应的,除非我们指定具体值。在 lazyvstack 中则相反,它约束的是每个 item 的宽度。我们可以这样理解,lazyhstack 的视图在水平方向上的堆叠的,它需要在有限的高度范围内向水平方向上填充,所以需要在有限的高度范围内约束每个 item 的高度。lazyvstack 也可以作同样的理解,只是方向不同罢了。
这里的 size
是一个枚举类型:
public enum size { // 一个使用指定尺寸的项目 case fixed(cgfloat) // 一个灵活的项目,可以指定最小或最大尺寸,默认最小尺寸为 10,最大为无限大 case flexible(minimum: cgfloat = 10, maximum: cgfloat = .infinity) // 在可用的空间内生成尽可能多的自适应尺寸的项目,可以指定最小或最大尺寸 case adaptive(minimum: cgfloat, maximum: cgfloat = .infinity) }
我们先了解这么多,下面结合具体实例理解。
lazyhgrid、lazyvgrid
我们先在要展示的 view 中添加如下属性:
// 天气,后面会据此生成随机数据 private let weathers = ["sun.max", "moon", "cloud.drizzle", "snow", "wind.snow"] // 6 种不同的布局样式 private let rowstyles = ["adaptive", "fixed", "flexible", "mix1", "mix2", "mix3"] // 选中的布局样式 @state private var styleselection: int = 0 // 依次对应 `rowstyles` 以及示例中的 6 种不同的布局样式 private let rows = [ // 自适应尺寸,最小高度为 60,根据视图的尺寸生成尽可能多的 item [griditem(.adaptive(minimum: 60))], // 三行,每行固定 item 高度为 80 array(repeating: griditem(.fixed(80)), count: 3), // 三行,因 .flexible 默认最最大高度为无限大,所以会撑满视图 array(repeating: griditem(.flexible(minimum: 60)), count: 3), // 第一行固定高度为 100,后面的 item 最小高度为 50,生成尽可能多的 item [griditem(.fixed(100)), griditem(.adaptive(minimum: 50))], // 第一行固定高度为 80,第二行因为是 .flexible,所以会撑满剩余空间 [griditem(.fixed(80)), griditem(.flexible(minimum: 60))], // 第一行固定高度为 120,第二行虽然是 .flexible,并不会撑满视图,因为后面还有 .adaptive, 其最小高度为 40,它的优先级最高,所以第二行的高度为 80 [griditem(.fixed(120)), griditem(.flexible(maximum: 80)), griditem(.adaptive(minimum: 40))] ]
styleselection
和 picker 配合使用,可以切换选中的布局样式,关于 picker 的使用,请参照前面的小节视图与交互/选择器的内容。
生成不同布局样式的主要代码:
scrollview(.horizontal) { lazyhgrid(rows: rows[styleselection]) { foreach(0..<999) { i in image(systemname: weathers[i % weathers.count]) .font(.title) .frame(minwidth: 40, maxheight: .infinity) .foregroundcolor(color.white) .background(color.blue) .cornerradius(8) } } } .frame(maxheight: .infinity)
最后就会生成示例所示的界面,请读者自行参照上文以及注释理解。
lazyvgrid 与 lazyhgrid 类似,不再赘述。下面是 lazyvgrid 的布局样式代码,与示例所示是一致的,供参考:
private let columns = [ [griditem(.adaptive(minimum: 60))],![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c4c83d48a06b440e9808b11f91b0ea1c~tplv-k3u1fbpfcp-watermark.image)![](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e307ad68faf646728007f34035b93145~tplv-k3u1fbpfcp-watermark.image) array(repeating: griditem(.fixed(80)), count: 3), array(repeating: griditem(.flexible(minimum: 60)), count: 3), [griditem(.fixed(100)), griditem(.adaptive(minimum: 50))], [griditem(.fixed(80)), griditem(.flexible(minimum: 60))], [griditem(.fixed(120)), griditem(.flexible(maximum: 80)), griditem(.adaptive(minimum: 40))] ]
本文为 eul 样章,如果您喜欢,请移步 appstore/eul 查看更多内容。