SwiftUI导航栏和状态栏-使它们具有相同的颜色

时间:2019-12-18 14:25:26

标签: ios swift xcode swiftui xcode11

我有一个新的应用程序,理想情况下,它的顶部将有一个稳定的深蓝色导航栏,并向上延伸至状态栏的后面。使这种不透明和正确的蓝色成为一种痛苦,但是我终于想出了办法,通过将以下内容放入包含NavigationView的View的init()中来使其工作:

init() {
    UINavigationBar.appearance().barTintColor = UIColor(named: "primaryBlue")
    UINavigationBar.appearance().backgroundColor = UIColor(named: "primaryBlue")
    UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)
    UINavigationBar.appearance().isOpaque = true
}

这将导致导航栏如下所示。它是蓝色的,但是状态栏仍然是白色,带有黑色文本(我希望它是深蓝色,带有白色文本)。

enter image description here

接下来,我知道我必须将状态栏的文本设置为“浅色内容”,并从Idiqual here找到了一个很好的解决方案,但这只是改变了状态栏的颜色“主题”,并且似乎没有办法使用这种方法来更改背景颜色。实施后,我现在有一个状态栏,可以在深色背景上显示浅色文本,但是我无法弄清楚如何获取NavigationView的深蓝色背景以扩展到状态栏的顶部。所以我剩下的是这个:

enter image description here

我尝试了几件事,例如将.edgesIgnoringSafeArea(.top)添加到几个不同的位置,包括NavigationView的右括号和父视图中的TabView,但没有任何效果。我是否缺少简单的东西?如何将NavigationBar的颜色扩展到屏幕顶部?这是我的Nav视图的代码。此结构称为“ FetchFrontPageArticles”:

var body: some View {
    NavigationView {
        VStack {
            List(self.fetcher.articles) { article in
                ...
            }.navigationBarTitle("", displayMode: .inline)
            .navigationBarItems(
                leading: Text(""),
                trailing: NavProfile()
            )
        }
    }
}

从此处显示的父TabView加载“ FetchFrontPageArticles”:

TabView(selection: $selection){
        FetchFrontPageArticles()
            .tabItem {
                VStack {
                    Image("house")
                    Text("Home")
                }
            }
            .tag(0)
        Text("Second View")
            .tabItem {
                VStack {
                    Image("list.dash")
                    Text("Browse")
                }
            }
            .tag(1)
        ...
    }
    .accentColor(Color("primaryYellow"))

我很想解决这个问题,而且看起来应该很简单。请帮忙!

更新:根据下面凯尔(Kyle)的回答,我已经尝试过这种方法。这是实现NavConfigurator后我的导航栏的屏幕截图(注意,该栏看起来更浅蓝色,因为透明效果起作用了):

enter image description here

4 个答案:

答案 0 :(得分:2)

以下对我有用:

为UINavigationController创建一个扩展,它将更改以下内容:

  • 导航栏背景颜色
  • 状态栏背景颜色
  • 导航栏标题颜色

    import UIKit
    
    extension UINavigationController {
        override open func viewDidLoad() {
            super.viewDidLoad()
    
            let appearance = UINavigationBarAppearance()
            //background color of the navigation and status bar
            appearance.backgroundColor = .black
            //color when the title is large
            appearance.largeTitleTextAttributes.updateValue(UIColor.white, forKey: NSAttributedString.Key.foregroundColor)
            //color when the title is small
            appearance.titleTextAttributes.updateValue(UIColor.white, forKey: NSAttributedString.Key.foregroundColor)
    
            // change the background- and title foregroundcolor for navigationbar
            navigationBar.standardAppearance = appearance
            navigationBar.scrollEdgeAppearance = appearance
            navigationBar.compactAppearance = appearance
            // change color of navigationbar items
            navigationBar.tintColor = UIColor.white
        }
    }
    

但是,这不会更改状态栏的前景色。为此,我们需要执行以下操作:

导入SwiftUI

class HostingController<Content> : UIHostingController<Content> where Content : View {
    @objc override dynamic open var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }
}

然后在我们的场景代理中

我们需要更换

window.rootViewController = UIHostingController(rootView: contentView)

window.rootViewController = HostingController(rootView: contentView)

答案 1 :(得分:1)

当我开始使用SwiftUI进行编码时,我遇到了同样的问题,经过大量研究,我找到了解决方案。

将以下代码放入SceneDelegate类中。

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {        
    let newAppearance = UINavigationBarAppearance()
    newAppearance.configureWithOpaqueBackground()
    newAppearance.backgroundColor = .black
    newAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]

    UINavigationBar.appearance().standardAppearance = newAppearance

    //Other code for displaying the first screen
}

UINavigationBarAppearance类用于更改导航栏的外观,可在iOS 13中使用。

上面的代码将更改所有控制器的导航栏样式。

答案 2 :(得分:0)

尝试使用UIViewControllerRepresentative

NavigationView {
    VStack {

         // your stuff

    }
    .accentColor(.white)
    .background(NavConfigurator { nav in
                nav.navigationBar.barTintColor = UIColor(named: "primaryBlue")
                nav.navigationBar.titleTextAttributes = [.foregroundColor : UIColor.white]
    })
}

编辑:忘记代表代码:

import SwiftUI

struct NavConfigurator: UIViewControllerRepresentable {

    var configure: (UINavigationController) -> Void = { _ in }

    func makeUIViewController(context: UIViewControllerRepresentableContext<NavConfigurator>) -> UIViewController {
        UIViewController()
    }

    func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<NavConfigurator>) {
        if let nc = uiViewController.navigationController {
            self.configure(nc)
        }
    }

}

答案 3 :(得分:0)

我在这个问题上苦苦挣扎了大约一个小时,最后我发现,如果您使用的是TabView,则需要将edgeIgnoringSafeArea添加到TabView而不是标签中的视图。

TabView {
   ViewA().tabItem.....

}.edgesIgnoringSafeArea(.top)

希望有帮助