我想知道 GeometryReader 是如何隐藏的,我有兴趣为学习目的构建一个自定义 GeometryReader!
坦率地说,我认为我们在 body 中使用的每个 View 都是一种 GeometryReaderView,不同之处在于它们不使用闭包来为我们发送代理,而且每个 View 都会回调它的代理会很烦人!因此apple决定给GeometryReader赋予Geometry阅读功能!所以这只是我的想法!
所以我正在寻找一种可能而且更可能是 SwiftUI 式的方法来读取 View 的代理,或者换句话说,请查看我的代码:
struct ContentView: View {
var body: some View {
CustomGeometryReaderView { proxy in
Color.red
.onAppear() {
print(proxy)
}
}
}
}
struct CustomGeometryReaderView<Content: View>: View {
@ViewBuilder let content: (CGSize) -> Content
var body: some View {
// Here I most find a way to reading the available size for CustomGeometryReaderView and reporting it back!
return Color.clear.overlay(content(CGSize(width: 100.0, height: 100.0)), alignment: .topLeading)
}
}
我还知道, View 的读取和报告代理不仅仅是 View 的大小,它还与坐标空间、框架有关……但现在为了让事情更容易解决,我只关注大小!所以大小很重要!
正如我所说,我对使用 UIKit 或 UIViewRepresentable 来读取大小不感兴趣!苹果可能会在掩护下使用类似的东西,也可能不会! 我的目标是尝试使用纯 SwiftUI 解决问题,或者你们中的一些人可能有一些关于 GeometryReader 源代码的好链接以供阅读和学习。
最佳答案
好的,SwiftUI 中有多种工具可以访问 View 大小(当然 GeometryReader
除外)。
问题当然是将该尺寸值转移到 View 构建阶段,因为只有 GeometryReader
允许在同一构建周期中执行此操作。
这是使用 Shape
的可能方法的演示 - 设计的形状没有自己的大小并消耗所有可用的东西,因此覆盖所有区域,并且已提供该区域作为输入。
使用 Xcode 13/iOS 15 测试
struct CustomGeometryReaderView<Content: View>: View {
@ViewBuilder let content: (CGSize) -> Content
private struct AreaReader: Shape {
@Binding var size: CGSize
func path(in rect: CGRect) -> Path {
DispatchQueue.main.async {
size = rect.size
}
return Rectangle().path(in: rect)
}
}
@State private var size = CGSize.zero
var body: some View {
// by default shape is black so we need to clear it explicitly
AreaReader(size: $size).foregroundColor(.clear)
.overlay(Group {
if size != .zero {
content(size)
}
})
}
}
备用:相同,但使用基于回调的模式
struct CustomGeometryReaderView<Content: View>: View {
@ViewBuilder let content: (CGSize) -> Content
private struct AreaReader: Shape {
var callback: (CGSize) -> Void
func path(in rect: CGRect) -> Path {
callback(rect.size)
return Rectangle().path(in: rect)
}
}
@State private var size = CGSize.zero
var body: some View {
AreaReader { size in
if size != self.size {
DispatchQueue.main.async {
self.size = size
}
}
}
.foregroundColor(.clear)
.overlay(Group {
if size != .zero {
content(size)
}
})
}
}
https://stackoverflow.com/questions/69918942/
相关文章:
c# - 当我更改继承类中同名方法的代码时,我不需要使用属性覆盖和虚拟。这是为什么?
angular - 检测关闭浏览器 Angular 12 的事件
javascript - 是否所有 WebAPI 都被推送到任务队列中?
node.js - 在不使用 NVM for Windows 的情况下在 Windows 上安装多个
jooq - jooq record 取数据时是否使用列索引?
amazon-web-services - AWS CodePipeline 角色无权在阶段的 "a
json - 通过 Postman 使用 PUT 请求更新 Contentful 帖子