#swift #swiftui #notifications #popup #queue
Вопрос:
Я пытаюсь реализовать пользовательские уведомления внутри приложения. Например, пользователь нажимает на кнопку, и может быть ограничение, и он получает всплывающее окно о том, что нужно сделать.
Ниже вы можете увидеть мой код, с которым отображается всплывающее окно при нажатии на кнопку
Параметры всплывающего окна:
public struct TopPopupOptions { public var yOffset: CGFloat public var hideAfter: TimeInterval? public var animation: Animation? public init( yOffset: CGFloat = 60, hideAfter: TimeInterval? = nil, animation: Animation? = nil, ) { self.yOffset = yOffset self.hideAfter = hideAfter self.animation = animation } }
Визуальный вид всплывающего окна, анимация:
protocol TopPopupModifierProtocol: ViewModifier { var shouldShowPopup: Bool { get set } var options: TopPopupOptions? { get } } struct TopPopupFade: TopPopupModifierProtocol { @Binding var shouldShowPopup: Bool let options: TopPopupOptions? func body(content: Content) -gt; some View { content .transition(AnyTransition.opacity.animation(options?.animation ?? .linear)) .opacity(shouldShowPopup ? 1 : 0) .zIndex(1) } }
Модификатор и расширение:
struct TopPopupModifierlt;TopPopupContent: Viewgt;: ViewModifier { @Binding var isPresented: Bool let options: TopPopupOptions let onDismiss: (() -gt; Void)? let content: () -gt; TopPopupContent func body(content: Content) -gt; some View { content .frame(maxWidth: .infinity, maxHeight: .infinity) .overlay ( VStack { if isPresented { self.content() .modifier(TopPopupSlide(shouldShowPopup: $isPresented, options: options)) .offset(x: 0, y: options.yOffset) } } ) } }
extension View { func topPopuplt;TopPopupContent: Viewgt;( isShowing: Bindinglt;Boolgt;, options: TopPopupOptions, onDismiss: (() -gt; Void)? = nil, @ViewBuilder content: @escaping () -gt; TopPopupContent) -gt; some View { self.modifier( TopPopupModifier(isPresented: isShowing, options: options, onDismiss: onDismiss, content: content) ) } }
Popup View:
struct TopPopupView: View { let title: String let onCloseTap: () -gt; Void var body: some View { GeometryReader { proxy in ZStack { Color.blue HStack(alignment: .center) { Image(systemName: "paperplane.fill") .foregroundColor(.white) .padding() Text(title) .font(.system(size: 16)) .foregroundColor(.white) Spacer() Image(systemName: "xmark") .frame(width: 14, height: 14) .foregroundColor(.white) .padding() .onTapGesture { onCloseTap() } } } .frame(height: 70) .padding(.horizontal, 15) } } }
Usage:
struct ContentView: View { @State var shouldShowPopup: Bool = false private let popupOptions = TopPopupOptions( hideAfter: .infinity ) var body: some View { VStack { Button("Show popup") { withAnimation { shouldShowPopup = true } } } .topPopup(isShowing: $shouldShowPopup, options: popupOptions) { TopPopupView(title: "Popup", onCloseTap: { withAnimation { shouldShowPopup = false } }) } } }
Ну что ж, еще раз. Я хотел бы добавить возможность добавлять всплывающие окна в очередь. Я нажимаю на кнопку, в результате у меня отображается одно всплывающее окно, с другой стороны, может появиться всплывающее окно другого типа, и оно встанет в очередь. После минимизации текущего всплывающего окна отображается то, которое было следующим в очереди. Заранее благодарю вас!