[英]SwiftUI update navigation bar title color
SwiftUI中如何更改導航欄標題顏色
NavigationView {
List{
ForEach(0..<15) { item in
HStack {
Text("Apple")
.font(.headline)
.fontWeight(.medium)
.color(.orange)
.lineLimit(1)
.multilineTextAlignment(.center)
.padding(.leading)
.frame(width: 125, height: nil)
Text("Apple Infinite Loop. Address: One Infinite Loop Cupertino, CA 95014 (408) 606-5775 ")
.font(.subheadline)
.fontWeight(.regular)
.multilineTextAlignment(.leading)
.lineLimit(nil)
}
}
}
.navigationBarTitle(Text("TEST")).navigationBarHidden(false).foregroundColor(.orange)
}
我試過.foregroundColor(.orange)
但它不起作用
也試過.navigationBarTitle(Text("TEST").color(.orange))
有什么幫助嗎?
沒有必要使用.appearance()
來全局執行此操作。
盡管 SwiftUI 不直接公開導航樣式,但您可以使用UIViewControllerRepresentable
解決這個問題。 由於 SwiftUI 在后台使用常規的UINavigationController
,因此視圖控制器仍然具有有效的.navigationController
屬性。
struct NavigationConfigurator: UIViewControllerRepresentable {
var configure: (UINavigationController) -> Void = { _ in }
func makeUIViewController(context: UIViewControllerRepresentableContext<NavigationConfigurator>) -> UIViewController {
UIViewController()
}
func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<NavigationConfigurator>) {
if let nc = uiViewController.navigationController {
self.configure(nc)
}
}
}
並使用它
struct ContentView: View {
var body: some View {
NavigationView {
ScrollView {
Text("Don't use .appearance()!")
}
.navigationBarTitle("Try it!", displayMode: .inline)
.background(NavigationConfigurator { nc in
nc.navigationBar.barTintColor = .blue
nc.navigationBar.titleTextAttributes = [.foregroundColor : UIColor.white]
})
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
在 SwiftUI 中,您不能直接更改 navigationTitleColor。 您必須像這樣在init()
中更改 UINavigation 的外觀,
struct YourView: View {
init() {
//Use this if NavigationBarTitle is with Large Font
UINavigationBar.appearance().largeTitleTextAttributes = [.foregroundColor: UIColor.red]
//Use this if NavigationBarTitle is with displayMode = .inline
UINavigationBar.appearance().titleTextAttributes = [.foregroundColor: UIColor.red]
}
var body: some View {
NavigationView {
List{
ForEach(0..<15) { item in
HStack {
Text("Apple")
.font(.headline)
.fontWeight(.medium)
.color(.orange)
.lineLimit(1)
.multilineTextAlignment(.center)
.padding(.leading)
.frame(width: 125, height: nil)
Text("Apple Infinite Loop. Address: One Infinite Loop Cupertino, CA 95014 (408) 606-5775 ")
.font(.subheadline)
.fontWeight(.regular)
.multilineTextAlignment(.leading)
.lineLimit(nil)
}
}
}
.navigationBarTitle(Text("TEST")).navigationBarHidden(false)
//.navigationBarTitle (Text("TEST"), displayMode: .inline)
}
}
}
我希望它會奏效。 謝謝!!
我已經搜索了這個問題並找到了一篇很棒的文章,您可以將導航欄樣式的設置包裝為視圖修飾符。
檢查此鏈接。
注意:我相信你需要在這個例子中更新一些代碼,添加titleColor
參數。
struct NavigationBarModifier: ViewModifier {
var backgroundColor: UIColor?
var titleColor: UIColor?
init(backgroundColor: UIColor?, titleColor: UIColor?) {
self.backgroundColor = backgroundColor
let coloredAppearance = UINavigationBarAppearance()
coloredAppearance.configureWithTransparentBackground()
coloredAppearance.backgroundColor = backgroundColor
coloredAppearance.titleTextAttributes = [.foregroundColor: titleColor ?? .white]
coloredAppearance.largeTitleTextAttributes = [.foregroundColor: titleColor ?? .white]
UINavigationBar.appearance().standardAppearance = coloredAppearance
UINavigationBar.appearance().compactAppearance = coloredAppearance
UINavigationBar.appearance().scrollEdgeAppearance = coloredAppearance
}
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: UIColor?, titleColor: UIColor?) -> some View {
self.modifier(NavigationBarModifier(backgroundColor: backgroundColor, titleColor: titleColor))
}
}
之后,像這樣申請:
.navigationBarColor(backgroundColor: .clear, titleColor: .white)
我希望它會奏效。
在 iOS 14 中,SwiftUI 可以使用新的toolbar
修飾符自定義導航欄。
我們需要將放置類型ToolbarItem
的.principal
設置為新的toolbar
修飾符。 您甚至可以設置圖像等等。
NavigationView {
Text("My View!")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {
HStack {
Image(systemName: "sun.min.fill")
Text("Title")
.font(.headline)
.foregroundColor(.orange)
}
}
}
}
基於 Arsenius 的回答,我發現讓它持續工作的一種優雅方法是UIViewController
並在viewDidLayoutSubviews()
中進行配置。
用法:
VStack {
Text("Hello world")
.configureNavigationBar {
$0.navigationBar.setBackgroundImage(UIImage(), for: .default)
$0.navigationBar.shadowImage = UIImage()
}
}
執行:
extension View {
func configureNavigationBar(configure: @escaping (UINavigationController) -> Void) -> some View {
modifier(NavigationConfigurationViewModifier(configure: configure))
}
}
struct NavigationConfigurationViewModifier: ViewModifier {
let configure: (UINavigationController) -> Void
func body(content: Content) -> some View {
content.background(NavigationConfigurator(configure: configure))
}
}
struct NavigationConfigurator: UIViewControllerRepresentable {
let configure: (UINavigationController) -> Void
func makeUIViewController(
context: UIViewControllerRepresentableContext<NavigationConfigurator>
) -> NavigationConfigurationViewController {
NavigationConfigurationViewController(configure: configure)
}
func updateUIViewController(
_ uiViewController: NavigationConfigurationViewController,
context: UIViewControllerRepresentableContext<NavigationConfigurator>
) { }
}
final class NavigationConfigurationViewController: UIViewController {
let configure: (UINavigationController) -> Void
init(configure: @escaping (UINavigationController) -> Void) {
self.configure = configure
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let navigationController = navigationController {
configure(navigationController)
}
}
}
我采取了稍微不同的方法; 我只想更改標題文本顏色,而沒有其他關於NavigationBar
的內容。 以上面和這個為靈感,我找到了:
import SwiftUI
extension View {
/// Sets the text color for a navigation bar title.
/// - Parameter color: Color the title should be
///
/// Supports both regular and large titles.
@available(iOS 14, *)
func navigationBarTitleTextColor(_ color: Color) -> some View {
let uiColor = UIColor(color)
// Set appearance for both normal and large sizes.
UINavigationBar.appearance().titleTextAttributes = [.foregroundColor: uiColor ]
UINavigationBar.appearance().largeTitleTextAttributes = [.foregroundColor: uiColor ]
return self
}
}
這需要 iOS 14,因為UIColor.init(_ color: Color)
需要 iOS 14。
可以這樣利用:
struct ExampleView: View {
var body: some View {
NavigationView {
Text("Hello, World!")
.navigationBarTitle("Example")
.navigationBarTitleTextColor(Color.red)
}
}
}
這反過來產生:
我開發了一個自定義 SwiftUI 導航的小示例,可以提供完整的可視化自定義和程序化導航。 它可以用作 NavigationView 的替代品。
這是處理 currentView 和導航堆棧的 NavigationStack 類:
final class NavigationStack: ObservableObject {
@Published var viewStack: [NavigationItem] = []
@Published var currentView: NavigationItem
init(_ currentView: NavigationItem ){
self.currentView = currentView
}
func unwind(){
if viewStack.count == 0{
return
}
let last = viewStack.count - 1
currentView = viewStack[last]
viewStack.remove(at: last)
}
func advance(_ view:NavigationItem){
viewStack.append( currentView)
currentView = view
}
func home( ){
currentView = NavigationItem( view: AnyView(HomeView()))
viewStack.removeAll()
}
}
你可以看看這里:完整的例子和解釋:
PS:我不知道為什么這個被刪除了。 我認為它回答了這個問題,因為它是 NavigationView 的完美功能替代品。
在 SwiftUI 中使用以下代碼自定義顏色
這是主體背景顏色:-
struct ContentView: View {
var body: some View {
Color.red
.edgesIgnoringSafeArea(.all)
}
}
對於導航欄:-
struct ContentView: View {
@State var msg = "Hello SwiftUI😊"
init() {
UINavigationBar.appearance().backgroundColor = .systemPink
UINavigationBar.appearance().largeTitleTextAttributes = [
.foregroundColor: UIColor.white,
.font : UIFont(name:"Helvetica Neue", size: 40)!]
}
var body: some View {
NavigationView {
Text(msg)
.navigationBarTitle(Text("NAVIGATION BAR"))
}
}
}
對於其他 UI 元素顏色自定義
struct ContentView: View {
@State var msg = "Hello SwiftUI😊"
var body: some View {
Text(msg).padding()
.foregroundColor(.white)
.background(Color.pink)
}
}
init() {
// for navigation bar title color
UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor:UIColor.red]
// For navigation bar background color
UINavigationBar.appearance().backgroundColor = .green
}
NavigationView {
List {
ForEach(0..<15) { item in
HStack {
Text("Apple")
.font(.headline)
.fontWeight(.medium)
.color(.orange)
.lineLimit(1)
.multilineTextAlignment(.center)
.padding(.leading)
.frame(width: 125, height: nil)
Text("Apple Infinite Loop. Address: One Infinite Loop Cupertino, CA 95014 (408) 606-5775 ")
.font(.subheadline)
.fontWeight(.regular)
.multilineTextAlignment(.leading)
.lineLimit(nil)
}
}
}
.navigationBarTitle(Text("TEST")).navigationBarHidden(false)
}
如果您的內容為
struct MyContent : View {
...
}
然后你可以把它放在一個帶有紅色背景的導航視圖中:
NavigationView {
ZStack(alignment: .top) {
Rectangle()
.foregroundColor(Color.red)
.edgesIgnoringSafeArea(.top)
MyContent()
}
}
一旦我知道如何更新標題文本本身,我就會更新我的答案。
您可以使用SwiftUI-Introspect單獨設置它們,而不是設置會影響所有導航欄的appearance()
。
例子:
struct ContentView: View {
var body: some View {
NavigationView {
ScrollView {
Text("Hello world!")
}
.navigationTitle("Title")
}
.introspectNavigationController { nav in
nav.navigationBar.barTintColor = .systemBlue
}
}
}
結果:
肯定已經有一些很好的答案,但它們都只涵蓋部分工作:
來自@arsenius的絕佳解決方案 - 給出一個好的開始點
來自@EngageTheWarpDrive的優雅方式——這絕對提高了可用性
對於最新版本的 iOS 和 swiftUI @Thahir建議使用工具欄
很少有更多建議建議對UINavigationBar
使用UIAppearence
全局配置——因為對我來說,全局更改不是一個好主意,可能並不總是合適的。
我最終將所有提案合並到下一個代碼中:
為navigationBar
配置創建NavigationControllerRepresentable
和modifier
:
struct NavigationControllerLayout: UIViewControllerRepresentable { var configure: (UINavigationController) -> () = { _ in } func makeUIViewController( context: UIViewControllerRepresentableContext<NavigationControllerLayout> ) -> UIViewController { UIViewController() } func updateUIViewController( _ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<NavigationControllerLayout> ) { if let navigationContoller = uiViewController.navigationController { configure(navigationContoller) } } } extension View { func configureNavigationBar(_ configure: @escaping (UINavigationBar) -> ()) -> some View { modifier(NavigationConfigurationViewModifier(configure: configure)) } } struct NavigationConfigurationViewModifier: ViewModifier { let configure: (UINavigationBar) -> () func body(content: Content) -> some View { content.background(NavigationControllerLayout(configure: { configure($0.navigationBar) })) } }
修改navigationBar
以滿足您的要求(例如 bg 顏色和其他道具):
extension UINavigationBar { enum Appearence { case transparent case defaultLight case colored(UIColor?) var color: UIColor { ... } var appearenceColor: UIColor { ... } var tint: UIColor { .... } var effect: UIBlurEffect? { .... } } func switchToAppearence(_ type: Appearence) { backgroundColor = type.color barTintColor = type.tint // for iOS 13+ standardAppearance.backgroundColor = type.appearenceColor standardAppearance.backgroundEffect = type.effect // u can use other properties from navBar also simply modifying this function } }
如您所見,這里我們肯定需要在Color
和UIColor
之間建立一些橋梁。 從iOS 14
開始 - 你可以只是UIColor.init(_ color: Color)
,但在iOS 14
之前沒有這樣的方法,所以我最終得到了簡單的解決方案:
extension Color { /// Returns a `UIColor` that represents this color if one can be constructed /// /// Note: Does not support dynamic colors var uiColor: UIColor? { self.cgColor.map({ UIColor(cgColor: $0) }) } }
這不適用於動態顏色
結果你可以使用它如下:
// modifier to `NavigationView` .configureNavigationBar { $0.switchToAppearence(.defaultLight) }
希望這可能對某人有所幫助;)
我還沒有弄清楚如何在每個視圖的基礎上制作前景色,但我確實找到了一個簡單的背景色解決方法。
如果使用.inline
標題,則可以在NavigationView
頂部使用帶有矩形的VStack
:
NavigationView {
VStack() {
Rectangle()
.foregroundColor(.red)
.edgesIgnoringSafeArea(.top)
.frame(height: 0)
List {
Text("Hello World")
Text("Hello World")
Text("Hello World")
}
}
.navigationBarTitle("Hello World", displayMode: .inline)
// ...
請注意矩形如何使用0
和.edgesIgnoringSafeArea(.top)
的框架高度。
這是對我有用的解決方案。 您需要從作為 rootViewController 的 UINavigationController 開始。
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
let nav = setupNavigationController()
window.rootViewController = nav
self.window = window
window.makeKeyAndVisible()
}
}
func setupNavigationController() -> UINavigationController {
let contentView = ContentView()
let hosting = UIHostingController(rootView: contentView)
let nav = NavigationController(rootViewController: hosting)
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]
navBarAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
navBarAppearance.backgroundColor = UIColor.black
nav.navigationBar.standardAppearance = navBarAppearance
nav.navigationBar.scrollEdgeAppearance = navBarAppearance
nav.navigationBar.prefersLargeTitles = true
return nav
}
然后在您的內容視圖中:
struct ContentView: View {
@State private var isModalViewPresented: Bool = false
var body: some View {
List(0 ..< 10, rowContent: { (index) in
NavigationLink(destination: DetailView()) {
Text("\(index)")
}
})
.navigationBarItems(trailing: Button("Model") {
self.isModalViewPresented.toggle()
})
.sheet(isPresented: $isModalViewPresented, content: {
ModalView()
})
.navigationBarTitle("Main View")
}
}
如果您想在某些時候更改顏色,例如在模態視圖中,請使用此處給出的答案
struct ModalView: View {
var body: some View {
NavigationView {
Text("Hello, World!")
.navigationBarTitle("Modal View")
.background(NavigationConfigurator { nc in
nc.navigationBar.backgroundColor = UIColor.blue
nc.navigationBar.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
})
}
}
}
你可以繼承 UINavigationController 來改變狀態欄的顏色
class NavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
}
override var preferredStatusBarStyle: UIStatusBarStyle
{
.lightContent
}
}
.foregroundColor(.orange)
- изменяет внутренние представления NavigationView。
但是要更改導航視圖本身,您需要在init()
中使用UINavigationBar Appearance()
)
我一直在尋找這個問題,並找到了一篇關於它的好文章。 我通過這篇文章修改了你的代碼並取得了成功。 在這里,我如何解決這個問題:
struct ContentView: View {
init() {
let coloredAppearance = UINavigationBarAppearance()
// this overrides everything you have set up earlier.
coloredAppearance.configureWithTransparentBackground()
coloredAppearance.backgroundColor = .green
coloredAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.black]
// to make everything work normally
UINavigationBar.appearance().standardAppearance = coloredAppearance
UINavigationBar.appearance().scrollEdgeAppearance = coloredAppearance
}
var body: some View {
NavigationView {
List{
ForEach(0..<15) { item in
HStack {
Text("Apple")
.font(.headline)
.fontWeight(.medium)
.lineLimit(1)
.multilineTextAlignment(.center)
.padding(.leading)
.frame(width: 125, height: nil)
.foregroundColor(.orange)
Text("Apple Infinite Loop. Address: One Infinite Loop Cupertino, CA 95014 (408) 606-5775 ")
.font(.subheadline)
.fontWeight(.regular)
.multilineTextAlignment(.leading)
.lineLimit(nil)
.foregroundColor(.orange)
}
}
}
.navigationBarTitle(Text("TEST"))
}
// do not forget to add this
.navigationViewStyle(StackNavigationViewStyle())
}
}
你也可以在這里舉一些例子
我在我的獨立 Apple Watch 應用中遇到了這個限制。 盡管此修復程序在 SwiftUI 中並不嚴格,但我轉到了 Interface.storyboard 文件,選擇了托管控制器,選擇了右側的文件檢查器,然后在 Interface Builder Document 部分下設置了 Global Tint 旁邊的顏色。
注意:第二天重新訪問,可能我的一些問題是由我的有點不標准的設置引起的:我仍在運行 mojave,但手動添加了 13.4 支持文件(通常只能通過 xcode 11.4 獲得,這需要 catalina )。 我之所以提到這一點,是因為我 / 也有一些標簽欄自定義顏色問題,但我只是注意到這些問題只有在我實際插入手機並從 xcode 運行應用程序時才會顯現出來。 如果我拔掉插頭,只是正常運行應用程序,我沒有看到標簽欄問題,所以導航欄問題可能有一些相似之處......
(我會將其添加為對上述 arsenius 答案(當前接受的答案)的評論,但我沒有代表,所以......)
我正在使用該解決方案,並且在 13.4 之前它一直運行良好,這似乎已經破壞了它,至少對我而言。 經過大量的視圖層次跟蹤,看起來他們改變了一些事情,使得隱式 UINavigationController 不再像解決方法中描述的那樣通過傳遞的 UIViewController 輕松訪問。 它仍然在那里(離樹很遠),我們只需要找到它。
為此,我們可以遍歷視圖層次結構,直到找到導航欄,然后像往常一樣在其上設置所需的參數。 這需要一個新的發現功能,以及 NavigationConfigurator 結構的一些小改動,以及它的實例化......
首先,發現功能:
func find_navbar(_ root: UIView?) -> UINavigationBar?
{
guard root != nil else { return nil }
var navbar: UINavigationBar? = nil
for v in root!.subviews
{ if type(of: v) == UINavigationBar.self { navbar = (v as! UINavigationBar); break }
else { navbar = find_navbar(v); if navbar != nil { break } }
}
return navbar
}
修改 NavigationConfigurator 如下(請注意,我們不再關心傳入視圖,因為這不再可靠):
struct NavigationConfigurator: UIViewControllerRepresentable
{
@EnvironmentObject var prefs: Prefs // to pick up colorscheme changes
var configure: () -> Void = {}
func makeUIViewController(context: UIViewControllerRepresentableContext<NavigationConfigurator>) -> UIViewController { UIViewController() }
func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<NavigationConfigurator>) { self.configure() }
}
(在我的應用程序中,我有一個 Prefs 對象來跟蹤顏色等)
...然后,在實例化站點,執行以下操作:
MyView()
.navigationBarTitle("List", displayMode: .inline)
.navigationBarItems(trailing: navbuttons)
.background(NavigationConfigurator {
if self.prefs.UI_COLORSCHEME != Colorscheme.system.rawValue
{ if let navbar = find_navbar(root_vc?.view)
{ navbar.barTintColor = Colors.uicolor(.navbar, .background)
navbar.backgroundColor = .black
navbar.titleTextAttributes = [.foregroundColor: Colors.uicolor(.navbar, .foreground)]
navbar.tintColor = Colors.uicolor(.navbar, .foreground)
}
}
})
請注意,我在我的應用程序的其他地方捕獲了根視圖控制器,並在此處使用它傳遞給 find_navbar()。 您可能想以不同的方式進行操作,但是由於其他原因,我已經有了該變量……還有一些其他特定於我的應用程序的東西,例如與顏色相關的對象,但是您明白了。
https://stackoverflow.com/a/58427754/4709057這個答案有效,但如果您遇到navigationController 在明暗模式下為零的問題。 只需添加這個..不知道它為什么會起作用。
struct ContentView: View {
var body: some View {
NavigationView {
ScrollView {
Text("Don't use .appearance()!")
}
.navigationBarTitle("Try it!", displayMode: .inline)
.background(NavigationConfigurator { nc in
nc.navigationBar.barTintColor = .blue
nc.navigationBar.background = .blue
nc.navigationBar.titleTextAttributes = [.foregroundColor : UIColor.white]
})
}
.navigationViewStyle(StackNavigationViewStyle())
.accentColor(.red) <------- DOES THE JOB
}
}
使用 SwiftUI 的 WatchOS 導航標題顏色
watchOS 的旁注是您不需要擺弄導航顏色。 這是您需要更改的 Watch Accent 顏色。 在您的項目中進入 WatchProjectName->Asset->Accent 並更改它
https://developer.apple.com/documentation/watchkit/setting_the_app_s_tint_color
基於此https://stackoverflow.com/a/66050825/6808357 ,我創建了一個擴展,您可以在其中同時設置背景顏色和標題顏色。
import SwiftUI
extension View {
/// Sets background color and title color for UINavigationBar.
@available(iOS 14, *)
func navigationBar(backgroundColor: Color, titleColor: Color) -> some View {
let appearance = UINavigationBarAppearance()
appearance.configureWithTransparentBackground()
appearance.backgroundColor = UIColor(backgroundColor)
let uiTitleColor = UIColor(titleColor)
appearance.largeTitleTextAttributes = [.foregroundColor: uiTitleColor]
appearance.titleTextAttributes = [.foregroundColor: uiTitleColor]
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
return self
}
}
以下是如何使用它:
var body: some View {
NavigationView {
Text("Hello world!") // This could be any View (List, VStack, etc.)
.navigationTitle("Your title here")
.navigationBar(backgroundColor: .blue, titleColor: .white)
}
}
快樂編碼!
使用UINavigationBarAppearance
做到這一點的新方法
extension UINavigationController {
open override func viewDidLoad() {
super.viewDidLoad()
let standardAppearance = UINavigationBarAppearance()
standardAppearance.backgroundColor = .blue
standardAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]
standardAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
navigationBar.standardAppearance = standardAppearance
navigationBar.compactAppearance = standardAppearance
navigationBar.scrollEdgeAppearance = standardAppearance
}}
如果您需要單獨的樣式用於compactAppearance
,則可以scrollEdgeAppearance
extension UINavigationController {
open override func viewDidLoad() {
super.viewDidLoad()
let standardAppearance = UINavigationBarAppearance()
standardAppearance.backgroundColor = .blue
standardAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]
standardAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
let compactAppearance = UINavigationBarAppearance()
compactAppearance.backgroundColor = .red
let scrollEdgeAppearance = UINavigationBarAppearance()
scrollEdgeAppearance.backgroundColor = .yellow
navigationBar.standardAppearance = standardAppearance
navigationBar.compactAppearance = compactAppearance
navigationBar.scrollEdgeAppearance = scrollEdgeAppearance
}}
更多閱讀
如果您不介意全局更改它,我發現進入資產目錄並設置 AccentColor 有效。
對我有用的解決方案是使用 UINavigationBarAppearance() 方法,然后將 .id() 添加到 NavigationView。 這將在顏色更改時自動重繪組件。
現在,您可以根據狀態引擎進行反應性顏色更改。
var body: some Scene {
let color = someValue ? UIColor.systemBlue : UIColor.systemGray3
let custom = UINavigationBarAppearance()
custom.configureWithOpaqueBackground()
custom.backgroundColor = color
UINavigationBar.appearance().standardAppearance = custom
UINavigationBar.appearance().scrollEdgeAppearance = custom
UINavigationBar.appearance().compactAppearance = custom
UINavigationBar.appearance().compactScrollEdgeAppearance = custom
return WindowGroup {
NavigationView {
content
}
.id(color.description)
}
}
該解決方案建立在不使用任何庫也不全局應用UINavigationBarAppearance
的公認答案之上。
此解決方案通過添加 hack 解決了已接受答案的問題(例如不適用於初始視圖或不適用於大顯示模式)。
請注意,我個人不會在生產代碼中使用此 hack,但有趣的是,這些問題可以得到解決。 使用風險自負。
struct NavigationHackView: View {
@State private var isUsingHack = false
var body: some View {
NavigationView {
List {
NavigationLink {
Text("Detail view")
.navigationTitle("Detail view")
.navigationBarTitleDisplayMode(.inline)
} label: {
Text("Show details view")
}
}
.navigationTitle("Hack!")
.background(
NavigationConfigurator { navigationController in
// required for hack to work
_ = isUsingHack
navigationController.navigationBar.navigationBarColor(.red, titleColor: .white)
}
)
.onAppear {
// required for hack to work
DispatchQueue.main.async {
isUsingHack.toggle()
}
}
// required for hack to work, even though nothing is done
.onChange(of: isUsingHack) { _ in }
}
}
}
struct NavigationConfigurator: UIViewControllerRepresentable {
var configure: (UINavigationController) -> Void = { _ in }
func makeUIViewController(
context: UIViewControllerRepresentableContext<NavigationConfigurator>
) -> UIViewController {
UIViewController()
}
func updateUIViewController(
_ uiViewController: UIViewController,
context: UIViewControllerRepresentableContext<NavigationConfigurator>
) {
guard let navigationController = uiViewController.navigationController else {
return
}
configure(navigationController)
}
}
extension UINavigationBar {
func navigationBarColor(
_ backgroundColor: UIColor,
titleColor: UIColor? = nil
) {
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = backgroundColor
if let titleColor = titleColor {
appearance.titleTextAttributes = [.foregroundColor: titleColor]
appearance.largeTitleTextAttributes = [.foregroundColor: titleColor]
// back button appearance
tintColor = titleColor
}
standardAppearance = appearance
scrollEdgeAppearance = appearance
compactAppearance = appearance
if #available(iOS 15.0, *) {
compactScrollEdgeAppearance = appearance
}
}
}
Post iOS 14 easy way to do:
protocol CustomNavigationTitle: View {
associatedtype SomeView: View
func customNavigationTitle(_ string: String) -> Self.SomeView
}
extension CustomNavigationTitle {
func customNavigationTitle(_ string: String) -> some View {
toolbar {
ToolbarItem(placement: .principal) {
Text(string).foregroundColor(.red).font(.system(size: 18))
}
}
}
}
extension ZStack: CustomNavigationTitle {}
Suppose your root view of view is made with ZStack
it can be utilised below way
ZStack {
}. customNavigationTitle("Some title")
從iOS 14開始,您可以擁有任何您想要的自定義視圖(包括具有自定義顏色和字體的自定義文本)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {
VStack {
Text("Yellow And Bold Title")
.bold()
.foregroundColor(.yellow)
}
}
}
您還可以從iOS 16設置導航欄顏色,例如:
.toolbarBackground(.red, in: .navigationBar)
我使用 ViewModifier 為導航欄應用自定義顏色。 我不能說下面的代碼修改了實際的導航欄,但我發現這個工作比其他工作更好。
與 UINavigationBar.appearance() 不同,它並不適用於所有視圖。
struct NavigationBarStyle<S: ShapeStyle>: ViewModifier {
private var bgStyle: S
private var viewBackgroundColor: Color
init(_ bgStyle: S, viewBackgroundColor: Color) {
self. bgStyle = bgStyle
self.viewBackgroundColor = viewBackgroundColor
}
func body(content: Content) -> some View {
ZStack {
Color(UIColor.systemBackground)
.ignoresSafeArea(.all, edges: .bottom)
content
}
.background(bgStyle)
}
}
extension View {
func navigationBarStyle<S: ShapeStyle>(_ bgStyle: S, viewBackgroundColor: Color = Color(UIColor.systemBackground)) -> some View {
modifier(NavigationBarStyle(bgStyle, viewBackgroundColor: viewBackgroundColor))
}
}
注意 - 您必須在最頂部的視圖上應用此修改器才能工作。 例如 -
struct NewView: View {
var body: some View {
NavigationView {
VStack {
HStack {
Text("H Stack")
}
// .navigationBarStyle(Color.orange) not the right place
Text("Hello World")
}
.navigationBarStyle(Color.orange) // right place to apply
}
}
}
struct ContentView: View {
init() {
UINavigationBar.appearance().largeTitleTextAttributes = [.foregroundColor: UIColor(Color("Golden"))]
}
var body: some View {
NavigationView {
List(movies) { movie in
NavigationLink {
MovieDetail(movie: movie)
} label: {
MovieCell(movie: movie)
}
}
.navigationTitle("Movies")
}
}
}
使用 UINavigationBar.appearance().largeTitleTextAttributes 屬性更改導航欄標題顏色
我發現的最簡單的方法是:
init() {
UINavigationBar.appearance().tintColor = UIColor.systemBlue
}
除了 systemBlue,您還可以使用您希望的任何其他顏色。 您必須在“var body: some View {}”之外實現它。 您還可以添加:
@Environment(/.colorScheme) var colorScheme
在init()
之上,然后您可以使用 .dark 或 .light 在暗模式和亮模式下以您想要的方式更改顏色。 例子:
init() {
UINavigationBar.appearance().tintColor = UIColor(colorScheme == .dark ? .white : Color(#colorLiteral(red: 0.2196078449, green: 0.007843137719, blue: 0.8549019694, alpha: 1)))
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.