在 SwiftUI 中显示小吃店消息

Posted

技术标签:

【中文标题】在 SwiftUI 中显示小吃店消息【英文标题】:show snack bar message in SwiftUI 【发布时间】:2020-05-22 02:29:04 【问题描述】:

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

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

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】:

您可以使用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))
    

【讨论】:

这是一个不错且简单的实现,但是,消息背景视图是半透明的,我尝试使用不透明度值更改所有颜色但无济于事,您是否知道如何使其背景具有纯色而不是半透明? 我不明白。在上面的例子中,横幅背景是实心的,后面有阴影,当它出现在内容上时不是半透明的 这是因为显示消息的视图位于 VStack 下 如果我有一个只有 VStackZStack 的视图,当我在每个视图上使用 BannerModifier 时,如果我这样使用它就不会出现:ZStack ....banner(..)VStack....banner(...),要使其正常工作,我必须始终使用 ZStack 进行设置,并且必须将以下行作为 ZStack 中的最后一个元素:EmptyView().banner(...),您可以直接在任何不需要使用这种解决方法的视图? @JAHelia 解决您的问题的方法是 zIndex(_:)。默认情况下,zIndex 的值为 0(零)。您可以提供正值或负值来排列视图的重叠。链接:developer.apple.com/documentation/swiftui/group/3284926-zindex

以上是关于在 SwiftUI 中显示小吃店消息的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SwiftUI URLSession 中显示来自服务器的错误消息

SwiftUI中List数据源为空时如何在视图中心显示文本消息?

SwiftUI .fileImporter 在通过向下滑动关闭后无法再次显示

SwiftUI - 滚动到聊天应用程序的最新消息

SwiftUI 显示/关闭键盘

SwiftUI中ScrollView底部对齐内的VStack