简体   繁体   English

如果在 SwiftUI 中使用 NavigationView,如何更改背景颜色?

[英]How change background color if using NavigationView in SwiftUI?

I want to change background color for full screen.我想更改全屏的背景颜色。 I am using NavigationView , and I want to set Gray color for background (not default white)我正在使用NavigationView ,我想为背景设置灰色(不是默认白色)

struct ContentView : View {
    var body: some View {
        NavigationView {
            ScrollView {
                Text("Example")
            }
            .navigationBarTitle("titl")
        }
    }
}

Setting .background(Color.red) does not work in any place.设置.background(Color.red)在任何地方都不起作用。

preview预习

If you just embed your content in the NavigationView within a ZStack you should be able to throw the color in underneath your main content.如果您只是将您的内容嵌入到ZStack中的NavigationView ,您应该能够在主要内容下方添加颜色。

struct ContentView : View {
    var body: some View {
        NavigationView {
            ZStack {
                Color.red.edgesIgnoringSafeArea(.all)
                ScrollView {
                    Text("Example")
                }
                .navigationBarTitle("title")
            }
        }
    }
}

Adding to Mattis Schulte's answer, one of the side effects I've encountered is that the status bar will not inherit the background color.除了 Mattis Schulte 的回答之外,我遇到的副作用之一是状态栏不会继承背景颜色。

However when you scroll a List (for example) up toward the top of the view and iOS switches to an inline title view (with the centered NavigationBarTitle) it does color in the status bar area leaving a fairly undesirable user experience.但是,当您将列表(例如)向上滚动到视图顶部并且 iOS 切换到内联标题视图(具有居中的 NavigationBarTitle)时,它会在状态栏区域中显示颜色,从而留下相当不理想的用户体验。

The workaround I was able to use is:我能够使用的解决方法是:

import SwiftUI

let coloredNavAppearance = UINavigationBarAppearance()
   
struct ListView: View {

    init() {
        coloredNavAppearance.configureWithOpaqueBackground()
        coloredNavAppearance.backgroundColor = .systemBlue
        coloredNavAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]
        coloredNavAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
               
        UINavigationBar.appearance().standardAppearance = coloredNavAppearance
        UINavigationBar.appearance().scrollEdgeAppearance = coloredNavAppearance

    }

    var body: some View {
        NavigationView {
            Form {
                Section(header: Text("General")) {
                    HStack {
                        Text("ListView #1")
                        Spacer()
                        Text("data")
                            .multilineTextAlignment(.trailing)
                    }
                    HStack {
                        Text("ListView #2")
                        Spacer()
                        Text("data")
                            .multilineTextAlignment(.trailing)
                    }
                }

            }
            .navigationBarTitle("NavBar Title")
        }
    }
}


struct ListView_Previews: PreviewProvider {
    static var previews: some View {
        ListView()
    }
}

Hope this helps someone else.希望这对其他人有帮助。 Credit to https://sarunw.com/posts/uinavigationbar-changes-in-ios13/归功于https://sarunw.com/posts/uinavigationbar-changes-in-ios13/

A newest solution is having an extension for UINavigationController , as below:最新的解决方案是对UINavigationController进行扩展,如下所示:

extension UINavigationController {
    override open func viewDidLoad() {
        super.viewDidLoad()

    let standard = UINavigationBarAppearance()
    standard.backgroundColor = .red //When you scroll or you have title (small one)

    let compact = UINavigationBarAppearance()
    compact.backgroundColor = .green //compact-height

    let scrollEdge = UINavigationBarAppearance()
    scrollEdge.backgroundColor = .blue //When you have large title

    navigationBar.standardAppearance = standard
    navigationBar.compactAppearance = compact
    navigationBar.scrollEdgeAppearance = scrollEdge
 }
}

OR, The old one:或者,旧的:

Inside your struct initializer change UITableView color, as below:在您的结构初始化器中更改UITableView颜色,如下所示:

struct ContentView : View {
init() {
    UITableView.appearance().backgroundColor = .red
    }
var body: some View {
    NavigationView {
        ScrollView {
            Text("Example")
        }
        .navigationBarTitle("title")
    }
  }
}

Just add this to the initializer of your code UIScrollView.appearance().backgroundColor = UIColor.red .只需将此添加到您的代码UIScrollView.appearance().backgroundColor = UIColor.red But unfortunately, this solution has many side effects.但不幸的是,这种解决方案有很多副作用。

One little hack that you can do is add a text view that doesnt have any text in it and add the background color to what you want, something like the following:您可以做的一个小技巧是添加一个没有任何文本的文本视图,并将背景颜色添加到您想要的颜色,如下所示:

Text(" ")
    .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
    .background(Color.red)
    .edgesIgnoringSafeArea(.all)

Ok I just tried omar's solution, and unfortunately it doesn't work if there are any other views in the stack.好的,我刚刚尝试了 omar 的解决方案,不幸的是,如果堆栈中有任何其他视图,它就不起作用。

So the best answer I've seen for now that actually changes the underlying background color of the NavigationView (in OP's original question) is just setting the background color on the UIView appearance, as eluded to in this answer :所以我现在看到的最好的答案实际上改变了NavigationView的基础背景颜色(在 OP 的原始问题中)只是在 UIView 外观上设置背景颜色,正如这个答案中所隐含的:

UIView.appearance().backgroundColor = UIColor.red

Here is my solution as none of the others worked in my case so I thought I would share..这是我的解决方案,因为其他人都没有在我的情况下工作,所以我想我会分享..

So for the Navigation header bar colour, add an initialiser like this:因此,对于导航标题栏颜色,添加如下初始化程序:

struct ContentView: View {
    init() {
        UINavigationBar.appearance().backgroundColor = .red
    }
    var body: some View {
        NavigationView {
            ScrollView {
                ...
            }
        }
    }
}

And then for editing the ScrollView background color, you can do something like this: I have done for ListView but you can do it for ScrollView.然后为了编辑 ScrollView 背景颜色,你可以做这样的事情:我已经为 ListView 做了,但你可以为 ScrollView 做。

struct ListBackgroundColor: ViewModifier {

    let color: UIColor

    func body(content: Content) -> some View {
        content
            .onAppear() {
                UITableView.appearance().backgroundColor = self.color
                //(Optional) Edit colour of cell background
                UITableViewCell.appearance().backgroundColor = self.color
            }
    }
}   

extension View {
    func listBackgroundColor(color: UIColor) -> some View {
        ModifiedContent(content: self, modifier: ListBackgroundColor(color: color))
    }

}

UI Example https://imgur.com/a/TQ9c5Sc UI 示例https://imgur.com/a/TQ9c5Sc

The new way to do it 做到这一点的新方法

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

    }}

If you need separate styles for compactAppearance , scrollEdgeAppearance 如果您需要单独的样式用于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

}}

For more read 更多阅读

it's quite complicated to change bg color for NavigationView and keep it working properly like minification / magnification during content scrolling and also keeping safe areas更改 NavigationView 的 bg 颜色并使其正常工作(如内容滚动期间的缩小/放大以及保持安全区域)非常复杂

NavigationView-color-customisation on github here i posted common problems and solutions about color customisation in SwiftUI app github上的NavigationView-color- customisation 这里我发布了关于SwiftUI应用程序中颜色自定义的常见问题和解决方案

also if you really want to change bg color in ALL navgiationViews, prev comment's first part about Extension on UINavigationController looks good此外,如果您真的想更改所有导航视图中的 bg 颜色,则上一条关于 UINavigationController 扩展的第一部分评论看起来不错

NavigationView in SwiftUI and UINavigationBar in UIKit are just as cumbersome, and I have a third-party open source solution for iOS system navigation bars that I hope will help you solve the problem. SwiftUI 中的 NavigationView 和 UIKit 中的 UINavigationBar 一样麻烦,我有第三方开源的 iOS 系统导航栏解决方案,希望能帮到你解决问题。

Git repo: NXNavigationExtension Git 存储库: NXNavigationExtension

Change NavigationView color:更改 NavigationView 颜色:

struct ContentView: View {
    
    var body: some View {
        NavigationView {
            NavigationLink {
                Text("Pop")
                    .padding()
                    .useNXNavigationView(onPrepareConfiguration: { configuration in
                        // Page2
                        configuration.navigationBarAppearance.backgroundColor = .green
                    })
            } label: {
                Text("Push")
                    .padding()
                    .useNXNavigationView(onPrepareConfiguration: { configuration in
                        // Page1
                        configuration.navigationBarAppearance.backgroundColor = .red
                    })
            }
        }
        .navigationViewStyle(.stack)
    }
    
}

📝 example 📝 例子

For the nav bar in iOS 16 +对于 iOS 16 + 中的导航栏

.toolbarBackground(.red, for: .navigationBar)

for iOS 14 and less适用于 iOS 14 及以下

UINavigationBar.appearance().barTintColor = UIColor.red

for iOS 15适用于 iOS 15

NavigationView {
            ZStack(alignment: .top) {
                GeometryReader { reader in
                    Color.red
                        .frame(height: reader.safeAreaInsets.top, alignment: .top)
                        .ignoresSafeArea()
                }

                // your content view
            }

It's hard to get a "one size fits all solution" but in general it's possible to do this by introspecting the "hidden" view controller and setting it's background color.很难获得“一刀切”的解决方案,但通常可以通过内省“隐藏”视图控制器并设置其背景颜色来做到这一点。 Best to use SwiftUI-Introspect for this.最好为此使用SwiftUI-Introspect In your case:在你的情况下:

struct ContentView : View {
    var body: some View {
        NavigationView {
            ScrollView {
                Text("Example")
            }
            .navigationBarTitle("titl")
            .introspectViewController { vc in
                vc.view.backgroundColor = .clear
            }
        }
    }
}

It's possible that your view composition is different.您的视图组成可能不同。 To find the correct view debug your view hierarchy in Xcode and set the backgroundColor on it.要找到正确的视图,请在 Xcode 中调试您的视图层次结构并在其上设置backgroundColor This could be via vc.parent or vc.parent.subviews or elsewhere in your view hierarchy.这可能是通过vc.parentvc.parent.subviews或视图层次结构中的其他地方。

Caveat: In my case I needed to use the modifier on my NavigationLink destination.警告:就我而言,我需要在NavigationLink目标上使用修饰符。

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

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