如何在SwiftUI中以模式方式推送下一个屏幕以使其满载

时间:2019-06-21 19:36:19

标签: ios swift swiftui

如何推送下一个SwiftUI视图,但将其显示在全屏上而又不拖延Xcode 10模式演示文稿之类的功能。

我当前的实现方式,但并没有推动全屏显示(向下拖动并在顶部显示空白):

const port = chrome.runtime.sendMessage({ name: "content" }, messageReceived);
const root = document.documentElement;

function messageReceived(message) {
    if (message) {
        style(message);
    } else {
        console.warn("No selected theme.");
    }
}

3 个答案:

答案 0 :(得分:3)

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()
        }
    }
}

答案 1 :(得分:0)

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

时却可以

请确保您的模式视图以List或使用Spacer()之类的颜色填充屏幕,否则您仍然会看到其后的另一视图

struct ContentView: View {

    @State var showModal: Bool = 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 == true) {
                ModalView()
                    .background(Color.white)
                    .transition(transition);
            }
        }
    }
}

答案 2 :(得分:0)

简短的回答是,目前尚无好的方法来执行此操作。

这里有几种选择:

使用UIKit + Swift Hybrid

查看此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呈现的视图,除非隐藏了其导航栏和后退按钮
  • 通常,当将修饰符添加到给定布局中不是根View的View时,它将不再是全屏模式。

有关此内容的详细信息,请参见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())
    }
}

它也有问题: