Tom*_*mas 16 background inline navigationview swiftui
我刚刚开始在 SwiftUI 中编码并遇到了一个问题。我需要为导航栏(NavigationView)的背景赋予不同的颜色。当我从一个视图转到下一个视图时,颜色会发生变化。我需要让它为“内联”的 navigationBarTitleDisplayMode 工作。
我尝试了SwiftUI update navigation bar title color中提出的解决方案 ,但这些解决方案都不能完全满足我的需要。
对该帖子的回复中的解决方案适用于内联: 使用 UIViewControllerRepresentable。然而,当我们第一次打开视图时,它会显示前一个视图的颜色一秒钟,然后再更改为新颜色。我想避免这种情况,并在所有内容出现在屏幕上时立即显示颜色。有没有办法做到这一点?
这个其他解决方案也不起作用:在 init() 中更改 UINavigation 的外观,因为当我在 init() 中设置背景时,它将更改应用程序中所有视图的背景。同样,我需要视图具有不同的背景颜色。
我尝试了类似于此解决方案的方法:修改工具栏,但它不允许我更改导航栏的颜色。
我尝试的另一个解决方案是:Creating navigationBarColor function,它基于:NAVIGATIONVIEW DYNAMIC Behind COLOR IN SWIFTUI。该解决方案适用于navigationBarTitleDisplayMode“large”,但是当将navigationBarTitleDisplayMode设置为“inline”时,它将以不同的颜色显示导航栏的背景颜色,就好像它被灰色/透明层覆盖一样。例如,它在“大”模式下显示的颜色是: 大模式下的红色 但是相反,它显示的颜色是: 内联模式下的红色
最后,我尝试了这个解决方案:子类化 UIViewController 并配置 viewDidLayoutSubviews(),但它也无法满足我的需求。
最接近我需要的解决方案是 1. 和 4.,但它们仍然不能 100% 工作。
有人知道如何使这些解决方案中的任何一个都适用于内联的 navigationBarTitleDisplayMode,能够更改不同布局中导航栏的背景颜色,并在显示视图后显示新颜色(无延迟)?
谢谢你!
顺便说一下,我使用的是 XCode 12.5。
以下是我正在使用的示例代码,以示例 4. 作为模型:
FirstView.swift
import SwiftUI
struct FirstView: View {
@State private var selection: String? = nil
var body: some View {
NavigationView {
GeometryReader { metrics in
VStack {
Text("This is the first view")
NavigationLink(destination: SecondView(), tag: "SecondView", selection: $selection) {
EmptyView()
}
Button(action: {
self.selection = "SecondView"
print("Go to second view")
}) {
Text("Go to second view")
}
}
}
}.navigationViewStyle(StackNavigationViewStyle())
}
}
struct FirstView_Previews: PreviewProvider {
static var previews: some View {
FirstView()
}
}
Run Code Online (Sandbox Code Playgroud)
SecondView.swift
在此屏幕上,如果我使用
.navigationBarTitleDisplayMode(.large)
Run Code Online (Sandbox Code Playgroud)
颜色将正确显示:导航栏为红色 但使用
.navigationBarTitleDisplayMode(.inline)
Run Code Online (Sandbox Code Playgroud)
上面有一个模糊:导航栏上有某种红色的模糊
import SwiftUI
struct SecondView: View {
@State private var selection: String? = nil
var body: some View {
GeometryReader { metrics in
VStack {
Text("This is the second view")
NavigationLink(destination: ThirdView(), tag: "ThirdView", selection: $selection) {
EmptyView()
}
Button(action: {
self.selection = "ThirdView"
print("Go to third view")
}) {
Text("Go to third view")
}
}
}
.navigationBarColor(backgroundColor: Color.red, titleColor: .black)
.navigationBarTitleDisplayMode(.inline)
}
}
struct SecondView_Previews: PreviewProvider {
static var previews: some View {
SecondView()
}
}
Run Code Online (Sandbox Code Playgroud)
ThirdView.swift
该视图在使用时正确显示颜色
.navigationBarTitleDisplayMode(.large)
Run Code Online (Sandbox Code Playgroud)
但如果改为
.navigationBarTitleDisplayMode(.inline)
Run Code Online (Sandbox Code Playgroud)
它也会显示颜色顶部的模糊。
import SwiftUI
struct ThirdView: View {
var body: some View {
GeometryReader { metrics in
Text("This is the third view")
}
.navigationBarColor(backgroundColor: Color.blue, titleColor: .black)
.navigationBarTitleDisplayMode(.large)
}
}
struct ThirdView_Previews: PreviewProvider {
static var previews: some View {
ThirdView()
}
}
Run Code Online (Sandbox Code Playgroud)
NavigationBarModifierView.swift
import SwiftUI
struct NavigationBarModifier: ViewModifier {
var backgroundColor: UIColor?
var titleColor: UIColor?
init(backgroundColor: Color, titleColor: UIColor?) {
self.backgroundColor = UIColor(backgroundColor)
let coloredAppearance = UINavigationBarAppearance()
coloredAppearance.configureWithTransparentBackground()
coloredAppearance.backgroundColor = UIColor(backgroundColor)
coloredAppearance.titleTextAttributes = [.foregroundColor: titleColor ?? .white]
coloredAppearance.largeTitleTextAttributes = [.foregroundColor: titleColor ?? .white]
coloredAppearance.shadowColor = .clear
UINavigationBar.appearance().standardAppearance = coloredAppearance
UINavigationBar.appearance().compactAppearance = coloredAppearance
UINavigationBar.appearance().scrollEdgeAppearance = coloredAppearance
UINavigationBar.appearance().tintColor = titleColor
}
func body(content: Content) -> some View {
ZStack{
content
VStack {
GeometryReader { geometry in
Color(self.backgroundColor ?? .clear)
.frame(height: geometry.safeAreaInsets.top)
.edgesIgnoringSafeArea(.top)
Spacer()
}
}
}
}
}
extension View {
func navigationBarColor(backgroundColor: Color, titleColor: UIColor?) -> some View {
self.modifier(NavigationBarModifier(backgroundColor: backgroundColor, titleColor: titleColor))
}
}
Run Code Online (Sandbox Code Playgroud)
版主请注意:请不要删除此帖子。我知道以前也有人问过类似的问题,但我特别需要一个没有得到解决的答案。请在随意删除之前先阅读,我工作需要这个。另外,我无法在每个解决方案中内联提出问题,因为我在 stackoverflow 中没有达到在那里编写所需的最低 50 分。
Moj*_*ini 18
您可以使用这两个简单的本机修饰符(都需要)将任何颜色设置为内联状态的任何工具栏背景颜色(包括导航栏)的背景颜色:
.toolbarBackground(.visible, for: .navigationBar)
.toolbarBackground(.yellow, for: .navigationBar)
Run Code Online (Sandbox Code Playgroud)
颜色将设置在整个栏上(直到屏幕的顶部边缘)。
toolbarBackground 一定是visible看颜色
两个修饰符都应该应用于content,而不是(NavigationStack或NavigationView)本身!
这适用于large和inline navigationBarTitleDisplayMode。

我想我有你想要的。它非常敏感......它是一个黑客,并且不是非常强大,所以按原样......
我通过让你的修改器返回一个清晰的导航栏来让它工作,然后这个答案的解决方案适合你。我什至向 ThirdView() 添加了一个 ScrollView,以确保向下滚动不会影响 in。 另请注意,您会丢失栏的所有其他内置效果,如半透明等。
编辑:我检查了代码。.navigationViewStyle 位于错误的位置。它喜欢位于 NavigaionView() 之外,而其他所有内容都需要位于内部。另外,我删除了在 FirstView() 中设置条形颜色的代码部分,因为它既多余又丑陋。我本来不想把它留在那里。
struct NavigationBarModifier: ViewModifier {
var backgroundColor: UIColor?
var titleColor: UIColor?
init(backgroundColor: Color, titleColor: UIColor?) {
self.backgroundColor = UIColor(backgroundColor)
let coloredAppearance = UINavigationBarAppearance()
coloredAppearance.configureWithTransparentBackground()
coloredAppearance.backgroundColor = .clear // The key is here. Change the actual bar to clear.
coloredAppearance.titleTextAttributes = [.foregroundColor: titleColor ?? .white]
coloredAppearance.largeTitleTextAttributes = [.foregroundColor: titleColor ?? .white]
coloredAppearance.shadowColor = .clear
UINavigationBar.appearance().standardAppearance = coloredAppearance
UINavigationBar.appearance().compactAppearance = coloredAppearance
UINavigationBar.appearance().scrollEdgeAppearance = coloredAppearance
UINavigationBar.appearance().tintColor = titleColor
}
func body(content: Content) -> some View {
ZStack{
content
VStack {
GeometryReader { geometry in
Color(self.backgroundColor ?? .clear)
.frame(height: geometry.safeAreaInsets.top)
.edgesIgnoringSafeArea(.top)
Spacer()
}
}
}
}
}
extension View {
func navigationBarColor(backgroundColor: Color, titleColor: UIColor?) -> some View {
self.modifier(NavigationBarModifier(backgroundColor: backgroundColor, titleColor: titleColor))
}
}
struct FirstView: View {
@State private var selection: String? = nil
var body: some View {
NavigationView {
GeometryReader { _ in
VStack {
Text("This is the first view")
NavigationLink(destination: SecondView(), tag: "SecondView", selection: $selection) {
EmptyView()
}
Button(action: {
self.selection = "SecondView"
print("Go to second view")
}) {
Text("Go to second view")
}
}
.navigationTitle("First")
.navigationBarTitleDisplayMode(.inline)
.navigationBarColor(backgroundColor: .red, titleColor: .black)
}
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
struct SecondView: View {
@State private var selection: String? = nil
var body: some View {
VStack {
Text("This is the second view")
NavigationLink(destination: ThirdView(), tag: "ThirdView", selection: $selection) {
EmptyView()
}
Button(action: {
self.selection = "ThirdView"
print("Go to third view")
}) {
Text("Go to third view")
}
}
.navigationTitle("Second")
.navigationBarTitleDisplayMode(.inline)
.navigationBarColor(backgroundColor: .blue, titleColor: .black)
}
}
struct ThirdView: View {
var body: some View {
ScrollView {
ForEach(0..<50) { _ in
Text("This is the third view")
}
}
.navigationTitle("Third")
.navigationBarTitleDisplayMode(.inline)
.navigationBarColor(backgroundColor: .green, titleColor: .black)
}
}
Run Code Online (Sandbox Code Playgroud)