SwiftUI:在NavigationLink目标上隐藏状态栏

时间:2020-03-12 12:38:54

标签: swiftui

我有一个主详细信息结构,在主文件上有一个列表,在明细页面上我想全屏显示网页,因此没有导航栏,也没有状态栏。用户可以通过手势(内部应用程序)向后导航。

我正在用

隐藏状态栏
.statusBar(hidden: true)

这适用于母版页,但不适用于详细信息页。

隐藏导航栏可与我的ViewModifier一起使用

public struct NavigationAndStatusBarHider: ViewModifier {
    @State var isHidden: Bool = false

    public func body(content: Content) -> some View {
        content
            .navigationBarTitle("")
            .navigationBarHidden(isHidden)
            .statusBar(hidden: isHidden)
            .onAppear {self.isHidden = true}
    }
}

extension View {
    public func hideNavigationAndStatusBar() -> some View {
        modifier(NavigationAndStatusBarHider())
    }
}

有什么主意吗?

4 个答案:

答案 0 :(得分:3)

出于好奇,我已经尝试了几个小时。终于,我开始工作了。

诀窍是,每当用户导航到详细信息视图时,都将在主视图中隐藏状态栏。这是在iPhone 11 Pro Max-13.3和Xcode版本11.3.1中测试的代码。希望你喜欢 ;)。编码愉快。

Main View Detail View

import SwiftUI
import UIKit
import WebKit

struct ContentView: View {
    var urls: [String] = ["https://www.stackoverflow.com", "https://www.yahoo.com"]
    @State private var hideStatusBar = false

    var body: some View {
        NavigationView {
            List {
                ForEach(urls, id: \.self) { url in
                    VStack {
                        NavigationLink(destination: DetailView(url: url)) {
                            Text(url)
                        }
                        .onDisappear() {
                            self.hideStatusBar = true
                        }
                        .onAppear() {
                            self.hideStatusBar = false
                        }
                    }
                }
            }
            .navigationBarTitle("Main")
        }
        .statusBar(hidden: hideStatusBar)
    }
}

struct DetailView: View {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    var url: String = ""

    var body: some View {
        VStack {
            Webview(url: url)
            Button("Tap to go back.") {
                self.presentationMode.wrappedValue.dismiss()
            }
            Spacer()
        }
        .hideNavigationAndStatusBar()
    }
}

public struct NavigationAndStatusBarHider: ViewModifier {
    @State var isHidden: Bool = false

    public func body(content: Content) -> some View {
        content
            .navigationBarTitle("")
            .navigationBarHidden(isHidden)
            .statusBar(hidden: isHidden)
            .onAppear {self.isHidden = true}
    }
}

struct Webview: UIViewRepresentable {
    var url: String
    typealias UIViewType = WKWebView

    func makeUIView(context: UIViewRepresentableContext<Webview>) -> WKWebView {
        let wkWebView = WKWebView()
        guard let url = URL(string: self.url) else {
            return wkWebView
        }

        let request = URLRequest(url: url)
        wkWebView.load(request)
        return wkWebView
    }

    func updateUIView(_ uiView: WKWebView, context: UIViewRepresentableContext<Webview>) {
    }
}

extension View {
    public func hideNavigationAndStatusBar() -> some View {
        modifier(NavigationAndStatusBarHider())
    }
}

答案 1 :(得分:1)

好吧,您观察到的行为是因为隐藏状态栏无法从NavigationView内部调用,而可以在外部进行。经过Xcode 11.2和(!)Xcode 11.4beta3的测试。

请在下面查看我的发现。

demo1 demo2

          Case1                         Case2

案例1:在任何堆栈容器中

struct TestNavigationWithStatusBar: View {
    var body: some View {
        VStack {
            Text("Hello, World!")
                .statusBar(hidden: true)
        }
    }
}

案例2:NavigationView

struct TestNavigationWithStatusBar: View {
    var body: some View {
        NavigationView {
            Text("Hello, World!")
                .statusBar(hidden: true)
        }
    }
}

在导航视图之外使用.statusBar(hidden:)的解决方案(修复/解决方法)。因此,您应该相应地更新修饰符(或重新考虑设计以使其分开)。

demo3

struct TestNavigationWithStatusBar: View {
    var body: some View {
        NavigationView {
            Text("Hello, World!")
        }
        .statusBar(hidden: true)
    }
}

答案 2 :(得分:1)

我有一个 NavigationView,其中包含一个呈现 fullScreenModal 的视图。我希望状态栏对 NavigationView 可见,但对 fullScreenModal 隐藏。我尝试了多种方法,但没有任何效果(似乎很多人都在 iOS14 上发现状态栏和 NavigationView 的错误)。

我已经确定了一个解决方案,该解决方案看起来很笨拙,但似乎有效,并且应该可以完成工作,直到错误得到修复。

将以下内容添加到您的 Info.plist

<key>UIStatusBarHidden</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>

然后在必要时在视图的 init 中添加以下内容(根据需要更改 true/false): UIApplication.shared.isStatusBarHidden = false

例如:

struct ContentView: View {

    init() {
        UIApplication.shared.isStatusBarHidden = true
    }

    var body: some View {
        Text("Hello, world!")
    }
}

它会给你一个已弃用的警告,但我希望这是一个临时修复。

答案 3 :(得分:1)

Xcode 12.5 和 IOS 14.6 的解决方案:

将以下内容添加到您的 Info.plist

<key>UIStatusBarHidden</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>

将以下 UIApplication.shared.isStatusBarHidden = false 添加到您的 AppDelegate.swift

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        UIApplication.shared.isStatusBarHidden = false // -> This

        return true
    }

然后,您可以使用 UIApplication.shared.isStatusBarHidden 修饰符在应用中的任何位置隐藏和恢复状态栏。

示例:

struct Example: View {
    
    // I'm checking the safe area below the viewport 
    // to be able to detect iPhone models without a notch.
    @State private var bottomSafeArea = UIApplication.shared.windows.first?.safeAreaInsets.bottom
    
    var body: some View {
        
          Button {
              if bottomSafeArea == 0 {
                  UIApplication.shared.isStatusBarHidden = true // or use .toggle()
              }
          } label: {
              Text("Click here for hide status bar!")
                  .font(.title2)
        }
    }
}