swift - 在 SwiftUI 中显示小吃吧消息

标签 swift swiftui snackbar

有没有办法显示 HStack就像使用 SwiftUI 在 (n) 秒后关闭的 snackbar 消息?

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

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在它的上面。

最佳答案

您可以使用 ViewModifier创建横幅 View ,然后在 SwiftUI 中将其作为修饰符调用。
在修改器中使用 ZStack 在内容顶部显示横幅。
这是创建横幅并显示在 View 顶部的简单示例

在您看来,您可以使用 .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))
    }
}

关于swift - 在 SwiftUI 中显示小吃吧消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60088262/

相关文章:

ios - 无法使用类型为 'AVCaptureDeviceInput' 的参数列表调用类型为 '(device: AVCaptureDevice!, error: inout NSError?)' 的初始值设定项

ios - 隐藏导航栏但保留后退按钮 - SwiftUI

swiftui - 有条件创建形状 - SwiftUI

ios - 添加 TabView 使 Navigation Bar 无法覆盖 SwiftUI 中的安全区域

java - 使用 getFont 时 android.content.res.Resources$NotFoundException

ios - RxSwift - 无法推断通用参数 'Self'

swift - 惰性属性的内存管理

ios - swift-如何在特定日期和时间打开日历应用程序?

android - 如何将 Android Snackbar 的初始对齐方式从底部更改为顶部?

flutter - Flutter:针对整个应用程序的SnackBar方法,修改Scaffold以跟踪当前显示的Scaffolds的BuildContext