【问题标题】:SwiftUI view with multiple ViewBuilder具有多个 ViewBuilder 的 SwiftUI 视图
【发布时间】:2020-06-09 16:08:17
【问题描述】:

我有一个表示单元格中一行的视图,如下所示

这很好用,但是三个水平元素(图像、标题/副标题、图像)被硬编码为它们各自的类型。

我想要一个通用的ThreeItemView,它可以接受任何类型的 3 个Views,并如图所示排列它们。这将允许我将相同的容器布局与任何其他视图类型重用。

我创建了一个需要三个 @ViewBuilders 的视图:

import Foundation
import SwiftUI

struct ThreeItemView<Start: View, Main: View, End: View>: View {

    let start: () -> Start
    let main: () -> Main
    let end: () -> End

    init(@ViewBuilder start: @escaping() -> Start,
        @ViewBuilder main: @escaping() -> Main,
        @ViewBuilder end: @escaping() -> End) {
        self.start = start
        self.main = main
        self.end = end
    }

    var body: some View {
        return HStack {
            start()
            main()
                .frame(minWidth: 0, maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
            end()
        }
        .frame(minWidth: 0, maxWidth: .infinity, maxHeight: 60, alignment: .leading)
    }
}

struct ThreeItemContainer_Previews: PreviewProvider {
    static var previews: some View {

        ThreeItemView(start: {
            Image(systemName: "envelope.fill")
        }, main: {
            Text("Main")
        }, end: {
            Image(systemName: "chevron.right")
        })
    }
}

这按预期工作,但 API 有点……麻烦。有什么方法可以让ThreeItemView 的使用更容易?

【问题讨论】:

    标签: swiftui


    【解决方案1】:

    如果你的意思是像下面这样的符号

    ThreeItemView {
        Start {
            Image(systemName: "envelope.fill")
        }
        Main {
            Text("Main")
        }
        End {
            Image(systemName: "chevron.right")
        }
    }
    

    然后找到下面修改你的模块

    typealias Start<V> = Group<V> where V:View
    typealias Main<V> = Group<V> where V:View
    typealias End<V> = Group<V> where V:View
    
    struct ThreeItemView<V1, V2, V3>: View where V1: View, V2: View, V3: View {
    
        private let content: () -> TupleView<(Start<V1>, Main<V2>, End<V3>)>
    
        init(@ViewBuilder _ content: @escaping () -> TupleView<(Start<V1>, Main<V2>, End<V3>)>) {
            self.content = content
        }
    
        var body: some View {
            let (start, main, end) = self.content().value
            return HStack {
                start
                main
                    .frame(minWidth: 0, maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
                end
            }
            .frame(minWidth: 0, maxWidth: .infinity, maxHeight: 60, alignment: .leading)
        }
    }
    
    struct ThreeItemContainer_Previews: PreviewProvider {
        static var previews: some View {
    
            ThreeItemView {
                Start {
                    Image(systemName: "envelope.fill")
                }
                Main {
                    Text("Main")
                }
                End {
                    Image(systemName: "chevron.right")
                }
            }
        }
    }
    

    【讨论】:

    • 很好,是的,我正在寻找这样的东西
    • 谢谢!正是我想要的。
    猜你喜欢
    • 2020-12-28
    • 2021-04-26
    • 1970-01-01
    • 2019-10-25
    • 2021-10-14
    • 1970-01-01
    • 1970-01-01
    • 2015-09-11
    • 2022-06-15
    相关资源
    最近更新 更多