在 SwiftUI 中显示小吃吧消息

JAH*_*lia 4 swift snackbar swiftui

有没有办法HStack使用 SwiftUI显示类似小吃店的消息,该消息在 (n) 秒后消失?

我有以下结构,它是我的消息的容器:

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

    let content: () -> Content

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

    var body: some View {
        content()
    }
}
Run Code Online (Sandbox Code Playgroud)

我调用MessageBuilder结构如下:

MessageBuilder {
            HStack {
                Image("MyImage")
                Text("Some Message")
            }
        }
Run Code Online (Sandbox Code Playgroud)

我有两个问题:

(1) 如何在屏幕顶部显示它然后自动关闭它(如SwiftMessages)?

(2) 我如何编写一个包装函数来显示任何 SwiftUI 上方的消息View,例如。在一个Storyboard基于项目的项目中,我们会传递像 topViewController 这样的东西,或者rootViewController为了UIView在它上面显示一个。

Mac*_*c3n 9

您可以使用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))
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @JAHelia 解决你的问题的方法是 zIndex(_:)。默认情况下,zIndex 的值为 0(零)。您可以提供正值或负值来排列视图的重叠。链接:https://developer.apple.com/documentation/swiftui/group/3284926-zindex (2认同)