SwiftUI 导航栏和状态栏 - 使它们颜色相同
SwiftUI Navigation Bar and Status Bar - Make them same color
我有一个新的应用程序,理想情况下,它的顶部会有一个深蓝色的导航栏,向上延伸到状态栏的后面。使这个不透明和正确的蓝色颜色很痛苦,但我终于想出了如何通过将以下内容放入包含 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
}
这会产生一个如下所示的导航栏。是蓝色的,但是状态栏还是白底黑字(我希望是深蓝底白字)。
接下来,我知道我必须制作状态栏的文本"light content",并从 Idiqual 找到了一个很好的解决方案,但这只是改变了颜色 "theme"栏的,并且似乎没有办法使用此方法更改背景颜色。实施后,我现在有一个状态栏,可以在深色背景上显示浅色文本,但我无法弄清楚如何让 NavigationView 的深蓝色背景扩展到状态栏的顶部。所以我剩下的是:
我尝试了几种方法,例如将 .edgesIgnoringSafeArea(.top) 添加到几个不同的地方,包括 NavigationView 的右括号以及父视图中的 TabView,但没有任何效果。我错过了一些简单的东西吗?如何将 NavigationBar 的颜色扩展到屏幕顶部?这是我的导航视图的代码。这个结构叫做 "FetchFrontPageArticles":
var body: some View {
NavigationView {
VStack {
List(self.fetcher.articles) { article in
...
}.navigationBarTitle("", displayMode: .inline)
.navigationBarItems(
leading: Text(""),
trailing: NavProfile()
)
}
}
}
"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"))
我很难解决这个问题,看起来应该很简单。请帮忙!
更新:根据下面 Kyle 的回答,我已经尝试过这种方法。这是实施 NavConfigurator 后我的导航栏的屏幕截图(注意栏看起来更浅的蓝色,因为透明效果开始发挥作用):
尝试使用 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)
}
}
}
当我开始使用 SwiftUI
编码时,我遇到了同样的问题,经过大量研究后我找到了解决方案。
将下面的代码放在 SceneDelegate
class.
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 用于更改导航栏的外观,可从 iOS 13.
以上代码将改变所有控制器的导航栏样式。
以下对我有效:
为 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
}
}
然后在我们的 scenedelegate
我们需要更换
window.rootViewController = UIHostingController(rootView: contentView)
和
window.rootViewController = HostingController(rootView: contentView)
在这个问题上折腾了大概一个小时,最后我发现如果你使用的是TabView,你需要将edgesIgnoringSafeArea添加到TabView而不是tab中的view。
TabView {
ViewA().tabItem.....
}.edgesIgnoringSafeArea(.top)
希望对您有所帮助
我有一个新的应用程序,理想情况下,它的顶部会有一个深蓝色的导航栏,向上延伸到状态栏的后面。使这个不透明和正确的蓝色颜色很痛苦,但我终于想出了如何通过将以下内容放入包含 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
}
这会产生一个如下所示的导航栏。是蓝色的,但是状态栏还是白底黑字(我希望是深蓝底白字)。
接下来,我知道我必须制作状态栏的文本"light content",并从 Idiqual
我尝试了几种方法,例如将 .edgesIgnoringSafeArea(.top) 添加到几个不同的地方,包括 NavigationView 的右括号以及父视图中的 TabView,但没有任何效果。我错过了一些简单的东西吗?如何将 NavigationBar 的颜色扩展到屏幕顶部?这是我的导航视图的代码。这个结构叫做 "FetchFrontPageArticles":
var body: some View {
NavigationView {
VStack {
List(self.fetcher.articles) { article in
...
}.navigationBarTitle("", displayMode: .inline)
.navigationBarItems(
leading: Text(""),
trailing: NavProfile()
)
}
}
}
"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"))
我很难解决这个问题,看起来应该很简单。请帮忙!
更新:根据下面 Kyle 的回答,我已经尝试过这种方法。这是实施 NavConfigurator 后我的导航栏的屏幕截图(注意栏看起来更浅的蓝色,因为透明效果开始发挥作用):
尝试使用 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)
}
}
}
当我开始使用 SwiftUI
编码时,我遇到了同样的问题,经过大量研究后我找到了解决方案。
将下面的代码放在 SceneDelegate
class.
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 用于更改导航栏的外观,可从 iOS 13.
以上代码将改变所有控制器的导航栏样式。
以下对我有效:
为 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
}
}
然后在我们的 scenedelegate
我们需要更换
window.rootViewController = UIHostingController(rootView: contentView)
和
window.rootViewController = HostingController(rootView: contentView)
在这个问题上折腾了大概一个小时,最后我发现如果你使用的是TabView,你需要将edgesIgnoringSafeArea添加到TabView而不是tab中的view。
TabView {
ViewA().tabItem.....
}.edgesIgnoringSafeArea(.top)
希望对您有所帮助