【发布时间】:2021-11-10 17:51:51
【问题描述】:
我刚开始在 SwiftUI 中编码,遇到了一个问题。我需要为导航栏(NavigationView)的背景赋予不同的颜色。当我从一个视图转到下一个视图时,颜色会发生变化。我需要让 navigationBarTitleDisplayMode 成为“内联”。
我尝试了以下解决方案: SwiftUI update navigation bar title color 但这些解决方案都不能完全满足我的需要。
-
该帖子的回复中的解决方案适用于内联: Using UIViewControllerRepresentable。然而,当我们第一次打开视图时,它会在更改为新颜色之前显示前一个视图的颜色一秒钟。我想避免这种情况,并在所有内容出现在屏幕上时立即显示颜色。有没有办法做到这一点?
-
这个其他解决方案也不起作用:Changing UINavigation's appearance in init(),因为当我在 init() 中设置背景时,它会改变应用程序中所有视图的背景。同样,我需要视图具有不同的背景颜色。
-
我尝试了类似于此解决方案的方法:Modifying Toolbar,但它不允许我更改导航栏的颜色。
-
我尝试的另一个解决方案是:Creating navigationBarColor function,它基于:NAVIGATIONVIEW DYNAMIC BACKGROUND COLOR IN SWIFTUI。此解决方案适用于 navigationBarTitleDisplayMode "large",但是当将 navigationBarTitleDisplayMode 设置为 "inline" 时,它将以不同的颜色显示导航栏的背景颜色,就好像它被灰色/透明层覆盖一样。例如,它在“大”模式下显示的颜色是: Red color in large mode 但相反,它显示了这种颜色: Red color in inline mode
-
最后,我尝试了这个解决方案:Subclassing UIViewController and configuring 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()
}
}
SecondView.swift
在这个屏幕上,如果我使用
.navigationBarTitleDisplayMode(.large)
颜色会正确显示:Navigation bar with red color 但是使用
.navigationBarTitleDisplayMode(.inline)
上面有一个模糊:Navigation bar with some sort of blur over red color
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()
}
}
ThirdView.swift
此视图在使用时正确显示颜色
.navigationBarTitleDisplayMode(.large)
但如果改为
.navigationBarTitleDisplayMode(.inline)
它也会在颜色上显示模糊。
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()
}
}
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))
}
}
版主注意:请不要删除此帖子。我知道以前有人问过类似的问题,但我特别需要一个没有解决的答案。乱删前请先阅读,我工作需要这个。此外,我不能在每个解决方案中内联提问,因为我在 stackoverflow 中没有写到那里所需的最低 50 分。
【问题讨论】:
-
我们无法用所提供的信息真正回答您的问题。请参阅:How do I ask a good question? 和 How to create a Minimal, Reproducible Example。我的建议是整理一个示例来展示您的尝试,然后让用户进行操作。否则,这将成为没有任何细节的一般性讨论,并且没有任何解决方案。
-
@Yrb 示例已添加。谢谢!
-
为什么
GeometryReaders有你的所有观点? -
@Yrb 添加了 GeometryReaders 是因为我们需要测量屏幕的大小,因为这是平面设计师制作的屏幕。我们经常需要测量比例等等。我尝试从所有地方删除 GeometryReaders,但问题仍然存在
标签: swiftui background inline navigationview