【问题标题】:How to Modally push next Screen to be full in SwiftUI如何在 SwiftUI 中模态地推动下一个屏幕充满
【发布时间】:2019-06-21 19:36:19
【问题描述】:

我怎样才能推送下一个 SwiftUI 视图但在全屏上显示它而不像 Xcode 10 模态演示那样向下滑动功能。

我当前的实现,但它没有推到全屏(启用下拉和顶部的间隙):

btn
.presentation(
      !showModal.value ?
           nil :
           Popover(content: destination, dismissHandler: onTrigger ?? {})
)

【问题讨论】:

标签: ios swift swiftui


【解决方案1】:

我认为目前唯一的方法是使用overlay()ZStack。使用overlay() 时我似乎无法进行转换,但使用ZStack 时我可以

只需确保您的模态视图使用List 或使用Spacer() 之类的内容填满屏幕,否则您仍然会看到它后面的另一个视图

struct ContentView: View {
    
    @State var showModal = false
    
    let transition = AnyTransition.move(edge: .bottom)
    
    var body: some View {
        ZStack {
            VStack {
                Button(action: {
                    withAnimation {
                        self.showModal = true
                    }
                }) {
                    Text("Show Modal")
                }
            }
            
            if self.showModal {
                ModalView()
                    .background(Color.white)
                    .transition(transition)
            }
        }
    }
}

【讨论】:

    【解决方案2】:

    fullScreenCover() 修饰符

    iOS 14 有一个名为 fullScreenCover() 的新 SwiftUI 修饰符。它是一种全屏模式的呈现方式。它的工作原理几乎与普通工作表相同。例如,这将在按下按钮时呈现全屏模式视图:

    struct ContentView: View {
     Button("Present Full Screen Modal!") {
                self.isPresented.toggle()
            }
            .fullScreenCover(isPresented: $isPresented) {
                NavigationView {
                    FullScreenModalView()
                        .toolbar {
                            ToolbarItem(placement: .navigationBarTrailing) {
                                Button(action: {
                                    isPresented = false
                                }, label: {
                                    Text("Dismiss")
                                })
                            }
                        }
                }
            }
        }
    }
    

    目标视图可以通过向下滑动或 Apple 推荐的更好的方式关闭,添加关闭按钮(已添加到导航工具栏中):

    struct FullScreenModalView: View {
        var body: some View {
            ZStack {
                Color.pink
                Text("This my full screen modal view")
                    .foregroundColor(.white)
            }
            .ignoresSafeArea()
            .onTapGesture {
                presentationMode.wrappedValue.dismiss()
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      简短的回答是,目前没有好的方法可以做到这一点。

      这里有几个选择:

      使用 UIKit + Swift 混合

      看到这个Present a new view in SwiftUI

      附加条件视图

      第一个答案涵盖了这个解决方案。基本上,您使用Bool 在“基本”视图之上或代替“基本”视图呈现“模态”视图。

      类似这样的:

      
      struct ModalView: View {
          var closeAction: (() -> Void) = {}
          var body: some View {
              ZStack {
                  Color.blue.edgesIgnoringSafeArea(.all)
                  VStack {
                      Text("I am a modal.")
                          .font(.largeTitle)
                          .fontWeight(.bold)
                          .foregroundColor(.white)
                          .padding()
                      Button(action: {
                          self.closeAction()
                      }, label: {
                          Text("OK, BYE!")
                              .foregroundColor(.white)
                              .padding()
                              .overlay(
                                  RoundedRectangle(cornerRadius: 5)
                                      .stroke(Color.white, lineWidth: 1)
                          )
                      })
                  }
              }
          }
      }
      
      struct BaseView: View {
          @State private var showModal = false
          var body: some View {
              ZStack {
                  if showModal {
                      ModalView(closeAction: {
                          withAnimation(.easeOut(duration: 0.25)) { self.showModal = false }
                      }).transition(.slideBottom)
                  } else {
                      VStack {
                          Button(action: {
                              withAnimation(.easeOut(duration: 0.25)) {
                                  self.showModal = true
                              }
                          }, label: {
                              Text("Open Modal")
                                  .padding()
                                  .overlay(
                                      RoundedRectangle(cornerRadius: 5)
                                          .stroke(Color.blue, lineWidth: 1)
                              )
                          })
                      }
                  }
              }.statusBar(hidden: true)
          }
      }
      

      它有自己的一系列问题:

      • 不是真正的模态演示(?)。 “基本”视图及其所有视图层次结构仍然存在于“模态”下。如果您想支持可访问性,这可能会很痛苦。您当然可以呈现条件模式而不是在基础视图之上。此设置有效,但需要编写得相当巧妙才能很好地扩展。
      • 您必须添加自己的动画过渡。
      • 如果基础视图嵌入到 NavigationView 根目录中则不起作用,除非它的导航栏被隐藏
      • 如果基础视图嵌入在 NavigationView 子视图中,则不起作用,即使用 NavigationLink 呈现的视图,除非其导航栏和后退按钮被隐藏
      • 一般来说,当修饰符添加到给定布局中不是根视图的视图时,它不再是全屏模式。

      如需对此进行全面探索,请参阅 https://github.com/piterwilson/SwiftUI-Modal-on-iPad/tree/master/iPadConditionalViewModal 和此 ViewModifier 我让代码更简洁 https://github.com/piterwilson/SwiftUI-FullscreenModalViewModifier

      使用NavigationView + NavigationLink

      您也可以使用NavigationView + NavigationLink 全屏显示,但最大的问题是您将无法自定义动画。它看起来像这样:

      struct ModalView: DismissableView {
          @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
          var body: some View {
              ZStack {
                  Color.green.edgesIgnoringSafeArea(.all)
                  VStack {
                      Text("I am a modal.")
                          .font(.largeTitle)
                          .fontWeight(.bold)
                          .foregroundColor(.white)
                          .padding()
                      Button(action: {
                          self.dismiss()
                      }, label: {
                          Text("OK, BYE!")
                              .foregroundColor(.white)
                              .padding()
                              .overlay(
                                  RoundedRectangle(cornerRadius: 5)
                                      .stroke(Color.white, lineWidth: 1)
                          )
                      })
                  }
              }.navigationBarBackButtonHidden(true)
          }
      }
      
      struct BaseView: View {
          var body: some View {
              NavigationView {
                  VStack {
                      NavigationLink(destination: ModalView()) {
                          Text("Open Modal")
                          .padding()
                          .overlay(
                              RoundedRectangle(cornerRadius: 5).stroke(Color.blue, lineWidth: 1)
                          )
                      }
                  }
              }
              .navigationViewStyle(StackNavigationViewStyle())
          }
      }
      

      它也有问题:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-29
        • 1970-01-01
        • 2021-06-03
        • 2020-04-24
        相关资源
        最近更新 更多