1

我尝试重新创建.toolbarApple 为其NavigationView. 我创建了一个自己的实现,NavigationStackView但也想使用.toolbar修饰符。

我可以使用环境对象和自定义视图修改器来工作,但是当我不应用.toolbar修改器时,这将不起作用,因为没有设置环境对象。

有一个更好的方法吗?苹果是如何做到这一点的?

例子:

import Foundation
import SwiftUI

class ToolbarData: ObservableObject {
    @Published var view: (() -> AnyView)? = nil
    
    init(_ view: @escaping () -> AnyView) {
        self.view = view
    }
}

struct NavigationStackView<Content: View>: View {
    @ViewBuilder var content: () -> Content
    @EnvironmentObject var toolbar: ToolbarData
    
    var body: some View {
        VStack(spacing: 0) {
            HStack(spacing: 0) {
                if (toolbar.view != nil) {
                    toolbar.view!()
                }
            }
            Spacer()
            content()
            Spacer()
        }
    }
}

struct NavigationStackToolbar<ToolbarContent: View>: ViewModifier {
    var toolbar: ToolbarContent
        
    func body(content: Content) -> some View {
        content
            .environmentObject(ToolbarData({
                AnyView(toolbar)
            }))
    }
}

extension NavigationStackView {
    func toolbar<Content: View>(_ content: () -> Content) -> some View {
        modifier(NavigationStackToolbar(toolbar: content()))
    }
}

struct NavigationStackView_Previews: PreviewProvider {
    static var previews: some View {
        NavigationStackView {
            Text("Test")
        }
        .toolbar {
            Text("Toolbar")
        }
    }
}

当前解决方案:

import Foundation
import SwiftUI

private struct ToolbarEnvironmentKey: EnvironmentKey {
    static let defaultValue: AnyView = AnyView(EmptyView())
}

extension EnvironmentValues {
    var toolbar: AnyView {
        get { self[ToolbarEnvironmentKey.self] }
        set { self[ToolbarEnvironmentKey.self] = newValue }
    }
}

struct NavigationStackView<Content: View>: View {
    @ViewBuilder var content: () -> Content    
    @Environment(\.toolbar) var toolbar: AnyView
    
    var body: some View {
        VStack(spacing: 0) {
            HStack(spacing: 0) {
                toolbar
            }
            Spacer()
            content()
            Spacer()
        }
    }
}

extension NavigationStackView {
    func toolbar<Content: View>(_ content: () -> Content) -> some View {
        self
            .environment(\.toolbar, AnyView(content()))
    }
}

struct NavigationStackView_Previews: PreviewProvider {
    static var previews: some View {
        NavigationStackView {
            Text("Test")
        }
        .toolbar {
            Text("Toolbar")
        }
    }
}
4

0 回答 0