показать сообщение закусочной в SwiftUI - PullRequest
0 голосов
/ 06 февраля 2020

Есть ли способ показать HStack как сообщение в виде закусочной, которое исчезает через (n) секунд, используя SwiftUI?

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

struct MessageBuilder<Content>: View where Content: View {

    let content: () -> Content

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

    var body: some View {
        content()
    }
}

Я называю структуру MessageBuilder следующим образом:

MessageBuilder {
            HStack {
                Image("MyImage")
                Text("Some Message")
            }
        }

У меня есть два вопроса:

(1), как я могу показать его в верхней части экрана, а затем автоматически - отклонить (например, SwiftMessages )?

(2) как мне написать функцию-обертку, которая выводит сообщение над любым SwiftUI View, например. в проектах, основанных на Storyboard, мы будем передавать что-то вроде topViewController или rootViewController, чтобы поверх него отображалось UIView.

1 Ответ

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

Вы можете использовать ViewModifier, чтобы создать представление баннера, а затем вызвать его как модификатор в вашем SwiftUI. Использование ZStack в вашем модификаторе для представления баннера поверх вашего контента. Вот простой пример создания баннера и показа сверху вашего представления

. Вы можете использовать .banner(data: $bannerData, show: $showBanner) для представления баннера

struct BannerData {
        var title: String
        var detail: String
        var type: BannerType
    }

    enum BannerType {
        case info
        case warning
        case success
        case error

        var tintColor: Color {
            switch self {
            case .info:
                return Color(red: 67/255, green: 154/255, blue: 215/255)
            case .success:
                return Color.green
            case .warning:
                return Color.yellow
            case .error:
                return Color.red
            }
        }
    }

struct BannerModifier: ViewModifier {

    @Binding var data: BannerData
    @Binding var show: Bool


    @State var task: DispatchWorkItem?

    func body(content: Content) -> some View {
        ZStack {
            if show {
                VStack {
                    HStack {
                        VStack(alignment: .leading, spacing: 2) {
                            Text(data.title)
                                .bold()
                            Text(data.detail)
                                .font(Font.system(size: 15, weight: Font.Weight.light, design: Font.Design.default))
                        }
                        Spacer()
                    }
                    .foregroundColor(Color.white)
                    .padding(12)
                    .background(data.type.tintColor)
                    .cornerRadius(8)
                    .shadow(radius: 20)
                    Spacer()
                }
                .padding()
                .animation(.easeInOut(duration: 1.2))
                .transition(AnyTransition.move(edge: .top).combined(with: .opacity))

                .onTapGesture {
                    withAnimation {
                        self.show = false
                    }
                }.onAppear {
                    self.task = DispatchWorkItem {
                        withAnimation {
                            self.show = false
                        }
                    }
                    // Auto dismiss after 5 seconds, and cancel the task if view disappear before the auto dismiss
                    DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: self.task!)
                }
                .onDisappear {
                    self.task?.cancel()
                }
            }
            content
        }
    }
}

extension View {
    func banner(data: Binding<BannerData>, show: Binding<Bool>) -> some View {
        self.modifier(BannerModifier(data: data, show: show))
    }
}
.
...