【问题标题】:SwiftUI: How to present a FullScreenCover SidewaysSwiftUI:如何横向呈现 FullScreenCover
【发布时间】:2021-01-24 08:55:39
【问题描述】:

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

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

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

您知道有什么方法可以让 FullsSreenCover 侧向打开,或者让 NavigationLink 在另一个视图中填满整个屏幕吗?

【问题讨论】:

    标签: swift swiftui swiftui-navigationlink


    【解决方案1】:

    在动画中使用overlay

    父视图

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

    全屏视图

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

    第二个选项是使用 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)
        }
    }
    

    内容视图和全屏

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

    【讨论】:

    • 如何在不推出初始视图的情况下实现这一点。我想在没有任何动画的情况下以全屏视图滑入 ContentView
    • @Zack 你试过第一种方法覆盖写动画关键字吗?
    • 我最初一直在使用它,直到我在 iOS 15 上发现导航栏的错误。我已经成功实现了第二个解决方案,唯一的问题是我不想为父视图设置动画,如果可能的话
    • 好的@Zack 通过使用第二种解决方案只需更改这些设置。 1. 为 presentcontroller 函数更新这一行 transition.type = CATransitionType.moveIn 2. 为dismissController 函数更新这一行transition.type = CATransitionType.reveal
    • 工作完美,感谢您的快速响应
    猜你喜欢
    • 1970-01-01
    • 2012-07-28
    • 2023-03-25
    • 2021-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-19
    相关资源
    最近更新 更多