簡體   English   中英

我們如何在 SwiftUI 中制作自定義 GeometryReader?

[英]How can we make a Custom GeometryReader in SwiftUI?

我想知道 GeometryReader 如何在掩護下工作,並且我有興趣構建一個自定義 GeometryReader 以用於學習目的

坦率地說,我認為我們在 body 中使用的每一個視圖都是 GeometryReaderView 的一種,不同之處在於它們不使用閉包來為我們發送代理,而且每一個視圖都回調它的代理會很煩人因此蘋果決定給幾何閱讀function 到 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)
        
    }
    
}

我也知道視圖的讀取和報告代理不僅僅是視圖的大小,它也與 CoordinateSpace、框架有關......但現在為了讓事情更容易解決,我只是在研究大小所以大小很重要

正如我所說,我對使用 UIKit 或 UIViewRepresentable 來讀取大小不感興趣。 可能蘋果會在掩護下使用類似的東西,也可能不會

好的,SwiftUI 中有幾個儀器可以訪問視圖大小(當然GeometryReader除外)。

問題當然是將該尺寸值轉移到視圖構建階段,因為只有GeometryReader允許在同一構建周期中執行此操作。

這是使用Shape的可能方法的演示 - 設計的形狀沒有自己的大小並消耗所有可用的東西,因此覆蓋所有區域,並已提供該區域 rect 作為輸入。

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

備份

每當我需要知道視圖的框架時,GeometryReader 就會變得不必要地復雜,並且“綁定首選項試圖每幀更新多次”警告是可怕的。 所以我決定創建CustomGeometryReader

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM