在SwiftUI中呈现新视图

时间:2019-11-20 16:15:51

标签: ios swiftui

我想单击一个按钮,然后在UIKit中显示一个像Filter这样的新视图 enter image description here

我已经看过“ How to present a new view using sheets”,但是我不想将其作为模式表附加到主视图。

我不想使用present modally,因为我不希望新视图和旧视图具有导航关系。

感谢您的帮助...

4 个答案:

答案 0 :(得分:4)

显示模式(iOS 13样式)

您只需要一个简单的sheet即可自行关闭:

struct ModalView: View {
    @Binding var presentedAsModal: Bool
    var body: some View {
        Button("dismiss") { self.presentedAsModal = false }
    }
}

并像这样显示它:

struct ContentView: View {
    @State var presentingModal = false

    var body: some View {
        Button("Present") { self.presentingModal = true }
        .sheet(isPresented: $presentingModal) { ModalView(presentedAsModal: self.$presentingModal) }
    }
}

请注意,我将presentingModal传递给了模态,以便您可以从模态本身中删除它,但是您可以摆脱它。


要使其真正呈现fullscreen(不仅是视觉效果)

您需要访问ViewController。因此,您需要一些辅助容器和环境材料:

struct ViewControllerHolder {
    weak var value: UIViewController?
}

struct ViewControllerKey: EnvironmentKey {
    static var defaultValue: ViewControllerHolder {
        return ViewControllerHolder(value: UIApplication.shared.windows.first?.rootViewController)

    }
}

extension EnvironmentValues {
    var viewController: UIViewController? {
        get { return self[ViewControllerKey.self].value }
        set { self[ViewControllerKey.self].value = newValue }
    }
}

然后您应该使用实现此扩展名:

extension UIViewController {
    func present<Content: View>(style: UIModalPresentationStyle = .automatic, @ViewBuilder builder: () -> Content) {
        let toPresent = UIHostingController(rootView: AnyView(EmptyView()))
        toPresent.modalPresentationStyle = style
        toPresent.rootView = AnyView(
            builder()
                .environment(\.viewController, toPresent)
        )
        self.present(toPresent, animated: true, completion: nil)
    }
}

最后

您可以像这样fullscreen

struct ContentView: View {
    @Environment(\.viewController) private var viewControllerHolder: UIViewController?

    var body: some View {
        Button("Login") {
            self.viewControllerHolder?.present(style: .fullScreen) {
                Text("Main") // Or any other view you like
            }
        }
    }
}

答案 1 :(得分:2)

对于iOS 14和Xcode 12:

struct ContentView: View {
    @State private var isPresented = false

var body: some View {
    Button("Show Modal with full screen") {
        self.isPresented.toggle()
    }
    .fullScreenCover(isPresented: $isPresented, content: FullScreenModalView.init)
    }
}
struct FullScreenModalView: View {
     @Environment(\.presentationMode) var presentationMode

var body: some View {
    VStack {
        Text("This is a modal view")
    }
    .frame(maxWidth: .infinity, maxHeight: .infinity)
    .background(Color.red)
    .edgesIgnoringSafeArea(.all)
    .onTapGesture {
        presentationMode.wrappedValue.dismiss()
    }
}
}

希望这个答案可以对大家有帮助!在下面评论您的结果。

参考:This Link

答案 2 :(得分:0)

这是一种简单的方法-转发视图。非常简单。

        struct ChildView: View{
           private  let colors: [Color] = [.red, .yellow,.green,.white]
           @Binding var index : Int
           var body: some View {
           let next = (self.index+1)  % MyContainer.totalChildren
             return   ZStack{
                    colors[self.index  % colors.count]
                     Button("myNextView \(next)   ", action: {
                    withAnimation{
                        self.index = next
                    }
                    }
                )}.transition(.asymmetric(insertion: .move(edge: .trailing)  , removal:  .move(edge: .leading)  ))
            }
        }

        struct MyContainer: View {
            static var totalChildren = 10
            @State private var value: Int = 0
            var body: some View {
                    HStack{
                        ForEach(0..<(Self.totalChildren) ) { index in
                            Group{
                            if    index == self.value {
                                ChildView(index:  self.$value)
                                }}
                            }
                }
                }
        }

答案 3 :(得分:-1)

免责声明:以下内容并非真正的“本机模式”,既不表现也不美观,但是如果有人需要自定义过渡一个视图到另一个视图,则仅激活顶部视图,以下该方法可能会有所帮助。

因此,如果您期望以下内容

custom SwiftUI modal

这是演示方法的简单代码(Corise动画和过渡参数可以根据需要更改)

struct ModalView : View {
    @Binding var activeModal: Bool
    var body : some View {
        VStack {
            Button(action: {
                withAnimation(.easeInOut(duration: 0.3)) {
                    self.activeModal = false
                }
            }) {
                Text("Hide modal")
            }
            Text("Modal View")
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
        .background(Color.green)
    }
}

struct MainView : View {
    @Binding var activeModal: Bool
    var body : some View {
        VStack {
            Button(action: {
                withAnimation(.easeInOut(duration: 0.3)) {
                    self.activeModal = true
                }
            }) {
                Text("Show modal")
            }
            Text("Main View")
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
        .background(Color.yellow)
    }
}

struct ModalContainer: View {
    @State var showingModal = false
    var body: some View {
        ZStack {
            MainView(activeModal: $showingModal)
                .allowsHitTesting(!showingModal)
            if showingModal {
                ModalView(activeModal: $showingModal)
                    .transition(.move(edge: .bottom))
                    .zIndex(1)
            }
        }
    }
}