Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use gradient for .toolbarBackground SwiftUI

Tags:

ios

swift

swiftui

I'm trying to set a custom gradient for the navigation .toolbarBackground but anytime I run its only using the first color from the LinearGradient.

.toolbar {
    ToolbarItem(placement: .navigationBarTrailing) {
        Menu {
            // MARK: 2 Actions
            // 1. logout
            // 2. Delete Account
            Button("Logout",action: logOutUser)
            
            Button("Delete Account",role: .destructive,action: deleteAccount)
        } label: {
            Image(systemName: "slider.horizontal.3")
                .rotationEffect(.init(degrees: 90))
                .tint(.white)
                .scaleEffect(0.8)
        }
    }
}
.navigationBarTitleDisplayMode(.inline)
.navigationTitle("My Garden")
.toolbarColorScheme(.dark, for: .navigationBar)
.toolbarBackground(.visible, for: .navigationBar)
.toolbarBackground(LinearGradient(gradient: Gradient(colors: [Color("Green1"), Color("Green2")]),startPoint: .bottomLeading,endPoint: .topTrailing))
like image 283
PoonDopolis Avatar asked Aug 08 '26 05:08

PoonDopolis


1 Answers

I came across the same issue lately and according to a blog post by Sarunw this is simply not possible as of iOS 16:

In the current beta, we can't use other ShapeStyle like LinearGradient.

I have filed a bug report and will update the post once I know it is the intended behavior or a bug.

→ https://sarunw.com/posts/swiftui-navigation-bar-color/#basic-usage

Alternative Solution

If you don’t want to wait for iOS 17 to maybe fix this issue, you can fall back to UIKit and use the UINavigationBarAppearance instead and use a gradient image. I guess you could even create the gradient image in code, but I simply ended up putting the gradient image into the asset catalog (default, without slicing) and feed it to the NavBar as backgroundImage.

There are quite a few tutorials out there showing this way, like this, this or this video. I the end they all end up with some form of this code:

struct MainNavigationBar: ViewModifier {
    init() {
        let appearance = UINavigationBarAppearance()
        
        // Custom gradient background
        appearance.backgroundImage = UIImage(named: "NavigationBarBackground")
        
        // Apply custom styling to all bar states
        UINavigationBar.appearance().standardAppearance = appearance
        UINavigationBar.appearance().scrollEdgeAppearance = appearance
        UINavigationBar.appearance().compactAppearance = appearance
        
        // Custom button color tinting
        // (buggy and not working for me for some reason)
        UINavigationBar.appearance().tintColor = .white
    }
    
    func body(content: Content) -> some View {
        content
    }
}

Now you can use this modifier on a NavigationStack to attach this style to the view and all of the subviews.

NavigationStack {
     // Your Content
}
.modifier(MainNavigationBar())
like image 74
alexkaessner Avatar answered Aug 09 '26 19:08

alexkaessner