在 SwiftUI 中创建 BaseView class

Creating BaseView class in SwiftUI

最近开始使用 Swiftlearning/developing 应用程序UI,构建 UI 组件似乎很容易。然而,在 SwiftUI 中努力创建一个 BaseView。我的想法是在 BaseView 中使用常见的 UI 控件,如 background 、 navigation 等,并将其他 SwiftUI 视图子类化以自动拥有基本组件。

通常您希望拥有共同的行为或共同的风格

1) 具有共同的行为:与泛型组合

假设我们需要创建一个 BgView,它是一个 View,以全屏图像作为背景。我们想随时重用 BgView 。你可以这样设计这个场景:

struct BgView<Content>: View where Content: View {
    private let bgImage = Image.init(systemName: "m.circle.fill")
    let content: Content

    var body : some View {
        ZStack {
            bgImage
                .resizable()
                .opacity(0.2)
            content
        }
    }
}

你可以在任何需要的地方使用BgView,你可以传递任何你想要的内容。

//1
struct ContentView: View {
    var body: some View {
        BgView(content: Text("Hello!"))
    }
}

//2
struct ContentView: View {
    var body: some View {
        BgView(content:
            VStack {
                Text("Hello!")
                Button(action: {
                    print("Clicked")
                }) {
                    Text("Click me")
                }
            }
        )
    }
}

2) 有一个共同的行为:组合 @ViewBuilder 闭包

考虑到所有 SwiftUI API,这可能是 Apple 首选的处理方式。让我们尝试以这种不同的方式设计上面的示例

struct BgView<Content>: View where Content: View {
    private let bgImage = Image.init(systemName: "m.circle.fill")
    private let content: Content

    public init(@ViewBuilder content: () -> Content) {
        self.content = content()
    }

    var body : some View {
        ZStack {
            bgImage
                .resizable()
                .opacity(0.2)
            content
        }
    }
}

struct ContentView: View {
    var body: some View {
        BgView {
            Text("Hello!")
        }
    }
}

通过这种方式,您可以像使用 VStackList 或其他任何方式一样使用 BgView

3) 要有共同的风格:创建视图修改器

struct MyButtonStyle: ViewModifier {
    func body(content: Content) -> some View {
        content
            .padding()
            .background(Color.red)
            .foregroundColor(Color.white)
            .font(.largeTitle)
            .cornerRadius(10)
            .shadow(radius: 3)
    }
}

struct ContentView: View {
    var body: some View {
        VStack(spacing: 20) {
            Button(action: {
                print("Button1 clicked")
            }) {
                Text("Button 1")
            }
            .modifier(MyButtonStyle())

            Button(action: {
                print("Button2 clicked")
            }) {
                Text("Button 2")
            }
            .modifier(MyButtonStyle())

            Button(action: {
                print("Button3 clicked")
            }) {
                Text("Button 3")
            }
            .modifier(MyButtonStyle())
        }
    }
}

这些只是示例,但通常您会发现自己使用上述设计风格之一来做事。

编辑:一个非常有用的link关于@functionBuilder(因此关于@ViewBuilder)https://blog.vihan.org/swift-function-builders/

我想到了如何在 SwiftUI 中创建一个 BaseView 以便在其他屏幕中常用

顺便说一下 步骤 .1 创建 ViewModifier

struct BaseScene: ViewModifier {
    
    /// Scene Title
    var screenTitle: String
    
    func body(content: Content) -> some View {
        VStack {
            HStack {
                Spacer()
                Text(screenTitle)
                    .font(.title)
                    .foregroundColor(.white)
                Spacer()
            }.padding()
            .background(Color.blue.opacity(0.8))
            content
        }
    }
}

步骤 .2 在视图中使用该 ViewModifer

struct BaseSceneView: View {
    
    var body: some View {
        
        VStack {
            Spacer()
            Text("Home screen")
                .font(.title)
            Spacer()
        }
        .modifier(BaseScene(screenTitle: "Screen Title"))
    }
}

struct BaseSceneView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            BaseSceneView()
        }
    }
}

您的输出如下: