Представление пользовательского представления поверх любого представления в SwiftUIIOS

Программируем под IOS
Ответить Пред. темаСлед. тема
Anonymous
 Представление пользовательского представления поверх любого представления в SwiftUI

Сообщение Anonymous »

Я знаю, что есть несколько сообщений на схожие темы, но в моем случае ни одна из них не сработала.
По сути, у меня сложное приложение, в котором есть главное представление и представляют собой несколько панелей (представленных в виде .sheet или .fullScreenCover поверх основного вида). Одновременно в главном представлении будет активна только одна панель (аналогично Apple Maps).
У меня есть собственное оповещение (в виде полноэкранной обложки), созданное в виде модификатора, но всякий раз, когда я хочу представить оповещение на листе, мне приходится прикрепить к этому листу специальный модификатор оповещения. Это добавляет много дублированного кода в приложении, поскольку я прикрепляю модификаторы к каждому листу и пробую что-то, где модификатор просто привязан к основному представлению и всякий раз, когда должно быть представлено предупреждение, независимо от того, какая панель/лист открыто в главном представлении, поверх активного листа должно отображаться предупреждение.
Ниже приведен мой код. Я попытался создать небольшой пример работающего кода, поскольку мое приложение сложное:

Код: Выделить всё

import SwiftUI

struct ContentView: View {
@State private var showSheet = false
@StateObject var viewModel: AppViewModel = AppViewModel()

var body: some View {
VStack {
Text("This is main view with multiple sheets.")
}
.padding(.bottom, 350.0)
.onAppear {
showSheet = true
}
.sheet(isPresented: $showSheet) {
SheetA().environmentObject(viewModel)
}
.customAlert(isPresented: $viewModel.showAlert) /// Wish to present an alert always from here, but the alert should be visible on top of any sheet that's open.
}
}

struct SheetA: View {
@EnvironmentObject var viewModel: AppViewModel

var body: some View {
VStack {
Text("This is sheet.")
Spacer()
Button {
viewModel.showAlertFromSheet()
} label: {
Text("Tap me")
}
}
.padding([.top, .bottom], 150.0)
.presentationDetents([.medium, .large], selection: $viewModel.panelDetent)
// Note: Works fine if I add this modifier to every sheet.  But trying to avoid that.
//.customAlert(isPresented: $viewModel.showAlert)
}
}

class AppViewModel: ObservableObject {
@Published var panelDetent: PresentationDetent = .medium

@Published var showAlert: Bool = false

func showAlertFromSheet() {
// Make http request call and show an alert on failure
self.showAlert = true
}
}
Код для пользовательского оповещения, если вы хотите передать его/выполнить:

Код: Выделить всё

extension View {
func customAlert(isPresented: Binding) -> some View {
return modifier(CustomAlertView(isPresented: isPresented))
}
}

struct CustomAlertView: ViewModifier {
@Binding var isPresented: Bool

init(isPresented: Binding) {
self._isPresented = isPresented
}

func body(content: Content) -> some View {
content.fullScreenCover(isPresented: $isPresented) {
alertView123.background(CustomAlertBackground())
}
.transaction { transaction in
transaction.disablesAnimations = true
}
}

private var alertView123: some View {
GeometryReader { geometry in
if self.$isPresented.wrappedValue {
VStack {
Image(systemName: "info.circle.fill").resizable().frame(width: 32.0, height: 32.0)
.padding(.top, 30).foregroundColor(Color.blue)

Text("Alert Title").foregroundColor(Color.primary).font(.title2).bold().multilineTextAlignment(.center)
.padding([.leading, .trailing], 20.0).padding(.top, 12.0)
Spacer()

Text("Alert Message").foregroundColor(Color.secondary).font(.body).multilineTextAlignment(.center)
.padding([.leading, .trailing], 20.0).padding(.top, 12.0)
Spacer()

// Buttons
}.fixedSize(horizontal: false, vertical: true).background(Color.gray.opacity(0.5))
.cornerRadius(28)
.clipped()
.padding([.leading, .trailing], 5.0)
.position(x: geometry.size.width/2, y: geometry.size.height/2)
.frame(width: 350.0)
}
}
}
}

struct CustomAlertBackground: UIViewRepresentable {
func makeUIView(context: Context) -> UIView {
return InnerView()
}

func updateUIView(_ uiView: UIView, context: Context) {}

private class InnerView: UIView {
override func didMoveToWindow() {
super.didMoveToWindow()
superview?.superview?.backgroundColor = UIColor(Color.gray.opacity(0.25))
}
}
}
В приведенном выше коде предупреждение не отображается, и я получаю сообщение: «В настоящее время поддерживается только представление одного листа. Следующий лист будет представлен, когда представленный в данный момент лист будет закрыт. " ошибка в Xcode. Я не хочу закрывать лист, а представить представление (в моем случае настраиваемое оповещение) поверх него.
Как лучше всего этого добиться, представив оповещение как полное Кажется, крышка экрана не работает?

Подробнее здесь: https://stackoverflow.com/questions/793 ... in-swiftui
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «IOS»