是否有一种方法可以显示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
。
答案 0 :(得分:5)
您可以使用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))
}
}