SwiftUI:如何横向呈现 FullScreenCover

标签 swift swiftui swiftui-navigationlink

我正在制作一个应用程序,其中多个页面/ View 嵌入到具有标签栏、菜单栏和标题的父 View 中,如下所示:

       HeaderView()
       MenuView()
       TabView(selection: $selected){
          HomeView()
          Page2View()
          Page3View()
          Page4View()
      }

当用户点击其中一个页面上的列表单元格时,我希望它以横向的详细 View 打开,而不是作为垂直打开的工作表/模态打开,即隐藏菜单栏、标题和标签栏。我已经尝试为此使用 FullScreenCover,但它总是自下而上显示,我无法弄清楚如何从侧面显示它。 我也尝试过使用 NavigationLink,但是当我不希望它们显示时它会保留标签栏、菜单栏和标题,而且我不知道如何使详细 View 全屏显示。

您知道有什么方法可以让 FullsSreenCover 横向打开,或者让 NavigationLink 在另一个 View 内时填满整个屏幕吗?

最佳答案

在动画中使用overlay

父 View

struct ContentView: View {
    @State var isShowSheet: Bool = false
    
    var body: some View {
        VStack{
            Button("Show Sheet") {
                withAnimation {
                    isShowSheet.toggle()
                }
            }
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
        .overlay(isShowSheet ? FullScreen(isShowSheet: $isShowSheet.animation()) : nil)
    }
}

全屏 View

struct FullScreen: View {
    
    @Binding var isShowSheet: Bool
    
    var body: some View {
        Color.blue
            .transition(.move(edge: .leading))
            .onTapGesture {
                isShowSheet = false
            }
            .edgesIgnoringSafeArea(.all)
    }
}

enter image description here

第二个选项是使用带有自定义动画的 UIViewController。 我已经使用此链接 (//https://stackoverflow.com/a/58494173/14733292) 中的 viewControllerHolder 扩展并添加了 CATransition()

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.presentController(toPresent)
    }
    
    func presentController(_ viewControllerToPresent: UIViewController) {
        let transition = CATransition()
        transition.duration = 0.25
        transition.type = CATransitionType.push
        transition.subtype = CATransitionSubtype.fromLeft
        self.view.window?.layer.add(transition, forKey: kCATransition)
        
        present(viewControllerToPresent, animated: false)
    }
    
    func dismissController() {
        let transition = CATransition()
        transition.duration = 0.25
        transition.type = CATransitionType.push
        transition.subtype = CATransitionSubtype.fromRight
        self.view.window?.layer.add(transition, forKey: kCATransition)
        dismiss(animated: false)
    }
}

ContentView 和全屏

struct ContentView: View {

    @Environment(\.viewController) private var viewControllerHolder: UIViewController?
    
    var body: some View {
        VStack{
            Button("Show Sheet") {
                viewControllerHolder?.present(style: .overFullScreen, builder: {
                    FullScreen()
                })
            }
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
    }
}

struct FullScreen: View {
    
    @Environment(\.viewController) private var viewControllerHolder: UIViewController?
    
    var body: some View {
        Color.blue
            .onTapGesture {
                viewControllerHolder?.dismissController()
            }
            .edgesIgnoringSafeArea(.all)
    }
}

enter image description here

关于SwiftUI:如何横向呈现 FullScreenCover,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65868660/

相关文章:

swift - 如何在执行 navigationLink 之前执行操作

ios: leftBarButtonItem.target 和 .action

ios - 在 segue IndexPath 期间在 tableview 中传递变量

swift - 在 Swift 中的 tableview 行之间拆分 JSON 响应的问题

SwiftUI:如何使用 iOS16/iPadOS16 NavigationSplitView 和 NavigationLink 更新远程子项的详细信息列

swift - macOS 上的 NavigationLink 未在同一 View 中打开

ios - 在 swiftui 中关闭 View

ios - Apple iOS Development Guide 上应该没有问题的时候

swift - SwiftUI 中 macOS 的侧边栏菜单

ios - 使用 SwiftUI 呈现多个模式表