Skip to content

Instantly share code, notes, and snippets.

@arthurschiller
Last active October 20, 2023 21:46
Show Gist options
  • Save arthurschiller/93667e49c87019c5ca14a2cb8ed15468 to your computer and use it in GitHub Desktop.
Save arthurschiller/93667e49c87019c5ca14a2cb8ed15468 to your computer and use it in GitHub Desktop.
Create a custom Navbar in SwiftUI with a gradient background
//
// SwiftUICustomGradientNavBar.swift
// SwiftUI Custom Gradient NavBar
//
// Created by Arthur Schiller on 06.03.23.
//
import SwiftUI
struct ContentView: View {
@State private var didSetupAppearance: Bool = false
init() {
setupAppearance()
}
var body: some View {
NavigationView {
Color.clear
.listStyle(.insetGrouped)
.navigationBarTitle("Hello there", displayMode: .automatic)
.navigationBarItems(
leading: makeBarButton(
image: Image(systemName: "paintbrush.fill")
) {
print("Leading Tapped…")
},
trailing: makeBarButton(
image: Image(systemName: "bookmark.fill")
) {
print("Trailing Tapped…")
}
)
}
}
func makeBarButton(
image: Image,
onTap: @escaping () -> Void
) -> some View {
Button {
onTap()
} label: {
image
.font(Font.system(size: 15, weight: .bold))
.tint(.white)
}
}
func setupAppearance() {
guard !didSetupAppearance else {
return
}
let appearance = UINavigationBarAppearance()
appearance.configureWithTransparentBackground()
// Custom background gradient & shadow
appearance.backgroundImage = Self.makeLinearGradient(
size: .init(width: 1, height: 1),
colors: [.red, .yellow]
)
appearance.shadowImage = UIImage()
// tint buttons
let buttonAppearance = UIBarButtonItemAppearance()
buttonAppearance.normal.titleTextAttributes = [
.foregroundColor: UIColor.white
]
appearance.buttonAppearance = buttonAppearance
appearance.backButtonAppearance = buttonAppearance
appearance.doneButtonAppearance = buttonAppearance
// Custom title styling
appearance.titleTextAttributes = [
.foregroundColor: UIColor.white,
.font: UIFont.systemFont(ofSize: UIFont.preferredFont(forTextStyle: .headline).pointSize, weight: .semibold, width: .expanded)]
appearance.largeTitleTextAttributes = [
.foregroundColor: UIColor.white,
.font: UIFont.systemFont(ofSize: UIFont.preferredFont(forTextStyle: .title1).pointSize, weight: .bold, width: .expanded)]
// Apply custom styling to all bar states
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
UINavigationBar.appearance().compactAppearance = appearance
didSetupAppearance = true
}
}
private extension ContentView {
static func makeLinearGradient(size: CGSize, colors: [UIColor]) -> UIImage {
let renderer = UIGraphicsImageRenderer(size: size)
let colors: [CGColor] = colors.map({ $0.cgColor })
let gradient = CGGradient(
colorsSpace: CGColorSpaceCreateDeviceRGB(),
colors: colors as CFArray,
locations: [0, 1]
)
return renderer.image { context in
if let gradient {
context.cgContext.drawLinearGradient(
gradient,
start: CGPoint(x: 0, y: 0),
end: CGPoint(x: size.width, y: size.height),
options: .init()
)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment