SwiftUI представление с несколькими ViewBuilder - PullRequest
1 голос
/ 25 февраля 2020

У меня есть представление, которое представляет строку в ячейке, которая выглядит следующим образом

view

Это хорошо работает, но три горизонтальных элемента (изображение, Заголовок / Подзаголовок, Изображение) жестко закодированы для их соответствующих типов.

Я хотел бы иметь универсальный c 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?

1 Ответ

1 голос
/ 26 февраля 2020

Если вы имеете в виду обозначения, подобные следующим

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")
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...