SwiftUI 5.0 中宝藏视图修改器 containerRelativeFrame 趣谈(下)

概览

小伙伴们都知道,为了将 SwiftUI 中多如牛毛的视图井然有序、有条不紊的组织起来,我们必须借助容器(Container)伏虎降龙般地威力。而如何最大限度的让容器中的子视图能根据容器尺寸安排自己的空间,则需要一些技术手段来洞幽察微。

在过去,我们往往使用 GeometryReader 来干这种“力气活”,不过自从有了 containerRelativeFrame 修改器,GeometryReader 从此就可以退居二线了。

在本篇博文中,您将学到如下内容:

  1. 滚动对齐
  2. 最大的自由度:按需定制
  3. 衍生应用:获取父容器尺寸

相信学完本课后,小伙伴们一定会对宝藏修改器 containerRelativeFrame 的使用豁然开朗、恍然大悟。那还等什么呢?让我们马上开始容器布局大冒险吧!

Let‘s go!!!;)


4. 滚动对齐

在上篇博文的代码中,我们已经可以颇为轻松的将子视图按照容器的可见尺寸(Visible Size in Container)进行等分,但是仍然无法保证容器内容每次滚动停止时正好对齐到某个子视图的边缘:

幸运的是,辅以同样是 SwiftUI 5.0 新引入的 Target Behavior 机制,我们即可一发入魂,完美解决这一问题:

ScrollView(.horizontal) {
    LazyHStack(spacing: 0) {
        ForEach(0..<10) { _ in
            Color.rand
                .containerRelativeFrame(
                    .horizontal,
                    count: 3,
                    span: 1,
                    spacing: 0
                )
                .frame(height: 300)
        }
    }
    .scrollTargetLayout()
}
.scrollTargetBehavior(.viewAligned)

如您所见,我们在上面的代码中为容器设置了滚动目标布局,并且用 scrollTargetBehavior 修改器方法确保滚动停止位置在子视图的边缘上:

现在无论我们怎样豪放不羁的拖拽滚动,子视图都会听话的停止在它们的边缘之上了。

5. 最大的自由度:按需定制

如果看到这里秃头小码农们还是觉得有些“笼中之鸟”、不甚自由的感觉,那么别急,containerRelativeFrame 还提供了另一种重载方法让我们能够更加逍遥自在的随意调整子视图的尺寸。

在 containerRelativeFrame 这种形式的修改器重载闭包中,我们可以得到当前父容器在某个轴上的可视尺寸。

于是,在下面的代码中,我们就利用这一点来确保子视图的宽度和高度分别为父容器可视尺寸的 1 / 3.3 和 1 / 5.5:

LazyHStack(spacing: 0) {
    ForEach(0..<10) { _ in
        Color.rand
            .containerRelativeFrame(
                [.horizontal, .vertical],
                alignment: .center
            ) { len, axis in
                switch axis {
                case .horizontal:
                    return len / 3.3
                case .vertical:
                    return len / 5.5
                }
            }
    }
}

运行即可见分晓:

6. 衍生应用:获取父容器尺寸

不知聪明的小伙伴们看了上节的代码是否会突然“灵机一动”,借助 containerRelativeFrame 修改器的这种重载形式,我们可以毫不费力的获取父容器的尺寸了:

struct ContentView: View {
    @State private var height = 0.0
    @State private var width = 0.0

    var body: some View {
        NavigationStack {
            ScrollView(.horizontal) {
                
                LazyHStack(spacing: 0) {
                    ForEach(0..<10) { _ in
                        Color.rand
                            .containerRelativeFrame(
                                [.horizontal, .vertical],
                                alignment: .center
                            ) { len, axis in
                                switch axis {
                                case .horizontal:
                                    width = len
                                    return len / 3.3
                                case .vertical:
                                    height = len
                                    return len / 5.5
                                }
                            }
                    }
                }
            }
            .safeAreaInset(edge: .bottom) {
                Text("Height: \(height, specifier: "%0.2f"), Width: \(width, specifier: "%0.2f")")
            }
        }
    }
}

在上面的代码中,我们在 containerRelativeFrame 内部的闭包里,借机保存了父容器的宽和高,并将它们显示了出来:

至此,我们已经完全掌握 Swift 5.0+ 中的 containerRelativeFrame 修改器了,小伙伴们还不赶紧给自己一个大大的赞吧!棒棒哒!💯

总结

在本篇博文中,我们继续讨论了如何利用 SwiftUI 5.0 新加入的 containerRelativeFrame 修改器来完成滚动对齐、以及更加无拘无束的根据父容器的视口来匹配子视图的尺寸。

感谢观赏,再会啦!8-)

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容