简体   繁体   English

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

[英]SwiftUI Navigation Bar and Status Bar - Make them same color

I have a new app that ideally will have a solid dark blue navigation bar at the top that extends up behind the status bar.我有一个新的应用程序,理想情况下,它的顶部会有一个深蓝色的导航栏,向上延伸到状态栏的后面。 It was a pain to make this opaque and the correct color of blue, but I finally figured out how to make it work by putting the following in the init() of my View that contains the NavigationView:使这个不透明和正确的蓝色颜色很痛苦,但我终于想出了如何通过将以下内容放在包含 NavigationView 的视图的 init() 中来使其工作:

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

This results in a navigation bar that looks like this.这会产生一个如下所示的导航栏。 It's blue, but the status bar is still white with black text (I want it to be dark blue with white text).它是蓝色的,但状态栏仍然是白色带黑色文本(我希望它是带白色文本的深蓝色)。

在此处输入图片说明

Next, I knew that I had to make the text of the status bar "light content", and found a good solution from Idiqual here , but this simply changes the color "theme" of the bar, and there doesn't appear to be a way to change the background color using this method.接下来,我知道我必须使状态栏的文本“轻内容”,并从 Idiqual here找到了一个很好的解决方案,但这只是改变了栏的颜色“主题”,似乎没有一种使用此方法更改背景颜色的方法。 After implementation, I now have a status bar that is ready to show light text on a dark background, but I'm unable to figure out how to get the dark blue background of the NavigationView to extend to the top of the status bar.实施后,我现在有一个状态栏,可以在深色背景上显示浅色文本,但我无法弄清楚如何让 NavigationView 的深蓝色背景扩展到状态栏的顶部。 So what I'm left with is this:所以我剩下的是这个:

在此处输入图片说明

I've tried several things, such as adding .edgesIgnoringSafeArea(.top) to several different places, including the closing bracket of the NavigationView and also the TabView that I have in the parent view, but nothing works.我尝试了几件事,例如将 .edgesIgnoringSafeArea(.top) 添加到几个不同的地方,包括 NavigationView 的右括号以及我在父视图中的 TabView,但没有任何效果。 Am I missing something simple?我错过了一些简单的东西吗? How do I extend the NavigationBar's color to the top of the screen?如何将 NavigationBar 的颜色扩展到屏幕顶部? Here is the code for my Nav view.这是我的导航视图的代码。 This struct is called "FetchFrontPageArticles":此结构称为“FetchFrontPageArticles”:

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

"FetchFrontPageArticles" is loaded from the parent TabView shown here: “FetchFrontPageArticles”是从此处显示的父 TabView 加载的:

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

I'm pretty stuck trying to resolve this, and it seems like it should be simple.我很难解决这个问题,看起来应该很简单。 Please help!请帮忙!

UPDATE: Per Kyle's answer below, I've already tried this approach.更新:根据下面凯尔的回答,我已经尝试过这种方法。 Here is a screenshot of my nav bar after implementing the NavConfigurator (notice the bar looks lighter blue, because the transparency effect comes into play):这是实现 NavConfigurator 后我的导航栏的屏幕截图(注意栏看起来更浅蓝色,因为透明效果开始发挥作用):

在此处输入图片说明

When I started coding with SwiftUI , I faced the same issue and after so much research I found the solution.当我开始使用SwiftUI编码时,我遇到了同样的问题,经过大量研究,我找到了解决方案。

Put the below code in the SceneDelegate class.将以下代码放在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 class is used for changing appearance of the navigation bar and it is available from iOS 13. UINavigationBarAppearance类用于更改导航栏的外观,可从 iOS 13 获得。

The above code will change the navigation bar style of all the controllers.上面的代码将改变所有控制器的导航栏样式。

The following works for me:以下对我有用:

create an extension for UINavigationController which will change the following:为 UINavigationController 创建一个扩展,它将改变以下内容:

  • navigationbar background color导航栏背景颜色
  • statusbar background color状态栏背景颜色
  • navigationbar title color导航栏标题颜色

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

however this will not change the statusbar foreground color.但是这不会改变状态栏的前景色。 for that we need to do the following:为此,我们需要执行以下操作:

import SwiftUI导入 SwiftUI

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

and then in our scenedelegate然后在我们的场景委托中

we need to replace我们需要更换

window.rootViewController = UIHostingController(rootView: contentView)

with

window.rootViewController = HostingController(rootView: contentView)

I have struggled on this problem for about one hour, finally I find that if you are using TabView, you need to add the edgesIgnoringSafeArea to TabView rather than the view in the tab.我在这个问题上挣扎了大约一个小时,最后我发现如果您使用的是 TabView,则需要将 edgeIgnoringSafeArea 添加到 TabView 而不是选项卡中的视图。

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

}.edgesIgnoringSafeArea(.top)

hope it helps希望能帮助到你

Try using a UIViewControllerRepresentative :尝试使用UIViewControllerRepresentative

NavigationView {
    VStack {

         // your stuff

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

Edit: Forgot representative code:编辑:忘记代表代码:

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

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM