|
// |
|
// 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() |
|
} |
|
} |