我们如何在 SwiftUI 中制作自定义 GeometryReader?

2024-04-09

我想知道 GeometryReader 是如何秘密工作的,并且我有兴趣构建一个用于学习目的的自定义 GeometryReader!

坦率地说,我认为我们在正文中使用的每个视图都是 GeometryReaderView 的一种,其区别在于它们不使用闭包来为我们发送代理,并且每个视图都会回调它的代理,这会很烦人!因此苹果决定将Geometry读取功能赋予GeometryReader!所以这只是我的想法!

因此,我正在寻找一种可能且更有可能的 SwiftUI-isch 方法来读取视图代理,或者换句话说,请参阅下面的代码:

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)
        
    }
    
}

我还知道,视图的读取和报告代理不仅仅是视图的大小,还与坐标空间、框架有关......但现在为了使事情更容易解决,我只是在处理大小!所以尺寸很重要!

正如我所说,我对使用 UIKit 或 UIViewRepresentable 来读取大小不感兴趣!苹果可能会在幕后使用类似的东西,也可能不会! 我的目标是尝试用纯 SwiftUI 解决问题,或者你们中的一些人可能有一些关于 GeometryReader 源代码的良好链接,以便阅读和学习它。


好吧,SwiftUI 中有几种工具提供了对视图大小的访问(除了GeometryReader当然)。

当然,问题是将这个大小值转移到视图构建阶段,因为只有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)
            }
        })
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我们如何在 SwiftUI 中制作自定义 GeometryReader? 的相关文章

随机推荐