[英]SwiftUI - How to close a fake Modal View - from the second view inside it, with a close button?
我有一個棘手的設計。 我試圖有一個關閉按鈕,從任何視圖中,在“假”模態視圖中(假因為它是全屏的,多虧了我在網上找到的代碼),它將關閉模態視圖。 現在關閉按鈕在模態視圖中打開的第一個視圖中工作,但我需要它在模態視圖的下一個視圖中也能工作,因為我在這個模態視圖中有一個流程來創建一個項目。
這是我啟動 ColorNewItemView 的視圖,我的假模態視圖。
struct RecapItemToAdd: View {
@State var isPresented: Bool = false
var body: some View {
NavigationView {
VStack {
Button(action: { withAnimation { self.isPresented.toggle()}}) {
Image(systemName: "pencil")
.resizable()
.renderingMode(.original)
.frame(width: 13, height: 17)
.foregroundColor(UIManager.hLightGrey)
}
}
ZStack {
VStack(alignment: .leading) {
ColorNewItemView(isPresenteded: self.$isPresented)
Spacer()
}
}
.background(Color.white)
.edgesIgnoringSafeArea(.all)
.offset(x: 0, y: self.isPresented ? 0 : UIApplication.shared.keyWindow?.frame.height ?? 0)
}
}
}
注意:我知道“keyWindow”已被棄用,但我不知道如何更改它。
使用 ColorNewItemView 啟動我的全屏模式視圖。 在此視圖中,關閉按鈕有效。
struct ColorNewItemView: View {
@State var selection: Int? = nil
@Binding var isPresenteded: Bool
var body: some View {
NavigationStackView {
VStack(alignment: .center) {
Button(action: {
self.isPresenteded = false
}) {
Image(systemName: "xmark.circle.fill")
.resizable()
.frame(width: 30, height: 30)
.foregroundColor(UIManager.hBlueLight)
}
Text("First View")
.font(UIManager.einaTitle)
.foregroundColor(UIManager.hDarkBlue)
Image("black-hoodie")
.resizable()
.renderingMode(.original)
.frame(width: 245, height: 300)
PushView(destination: Color2NewItemView(isPresenteded: self.$isPresenteded), tag: 1, selection: $selection) {
Button(action: {self.selection = 1}) {
Text("Avanti")
.font(UIManager.einaButton)
.foregroundColor(.white)
.frame(width: 291, height: 43)
.background(UIManager.buttonGradient)
.cornerRadius(6)
.shadow(color: UIManager.hBlueShadow, radius: 7, x: 0.0, y: 6.0)
}
}
}
}
}
}
現在我在模態視圖中有下一個視圖,關閉按鈕開始停止工作。
struct Color2NewItemView: View {
@Binding var isPresenteded: Bool
@State var selection: Int? = nil
var body: some View {
VStack(alignment: .center) {
Button(action: {
self.isPresenteded = false
}) {
Image(systemName: "xmark.circle.fill")
.resizable()
.frame(width: 30, height: 30)
.foregroundColor(UIManager.hBlueLight)
}
Text("Second View")
.font(UIManager.einaTitle)
.foregroundColor(UIManager.hDarkBlue)
Image("black-hoodie")
.resizable()
.renderingMode(.original)
.frame(width: 245, height: 300)
PushView(destination: FabricNewItemView(isPresenteded: $isPresenteded), tag: 1, selection: $selection) {
Button(action: {self.selection = 1}) {
Text("Tessuto")
.font(UIManager.einaButton)
.foregroundColor(.white)
.frame(width: 291, height: 43)
.background(UIManager.buttonGradient)
.cornerRadius(6)
.shadow(color: UIManager.hBlueShadow, radius: 7, x: 0.0, y: 6.0)
}
}
Spacer()
.frame(height: 18)
PopView{
Text("Back")
.font(UIManager.einaBodySemibold)
.foregroundColor(UIManager.hGrey)
}
}
}
}
附言。 我還必須使用一個名為 NavigationStack 的庫,因為我在頁面底部有一個自定義后退按鈕,並且導航視圖不允許我在不使用導航欄中的后退的情況下彈出。
綁定可能會在深層視圖層次結構中丟失,因此在接收到的級別上使用它更合適。
這是使用EnvironmentKey
的可能方法(與presentationMode
的想法相同)
引入一些關閉的輔助環境鍵
struct DismissModalKey: EnvironmentKey {
typealias Value = () -> ()
static let defaultValue = { }
}
extension EnvironmentValues {
var dismissModal: DismissModalKey.Value {
get {
return self[DismissModalKey.self]
}
set {
self[DismissModalKey.self] = newValue
}
}
}
因此,在您的頂部模式視圖中,您可以注入層次結構回調以解除
struct ColorNewItemView: View {
@State var selection: Int? = nil
@Binding var isPresented: Bool
var body: some View {
NavigationStackView {
// ... other code
}
.environment(\.dismissModal, { self.isPresented = false} ) // << here !!
}
}
因此此環境值現在可用於所有子視圖,您可以將其用作
struct Color2NewItemView: View {
@Environment(\.dismissModal) var dismissModal
@State var selection: Int? = nil
var body: some View {
VStack(alignment: .center) {
Button(action: {
self.dismissModal() // << here !!
}) {
// ... other code
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.