Skip to content
Blog SwiftUI: Create a Custom Navigation Bar

SwiftUI: Create a Custom Navigation Bar

In this article, we are not customizing a navigation view or a navigation stack. We are simply creating a custom View to be used as a navigation bar.

Custom Navigation Bar

 

//
//  CustomNavigationBar.swift
//  DK
//
//  Created by Dipin Krishna on 8/23/23.
//

import SwiftUI

struct CustomNavigationBar: View {
    var leftElement: (any View)? = Text("Back")
    var leftAction: (() -> Void)?
    var rightElement: (any View)?
    var rightAction: (() -> Void)?
    var title: (any View)?
    var inlineTitle: Bool? = true
    var backgroundColor: Color? = Color.black
    var foregroundColor: Color? = Color.white
    var height: CGFloat? = 44
    
    var body: some View {
        VStack (spacing: 0) {
            ZStack (alignment: .top) {
                HStack {
                    Spacer()
                    if let title {
                        if let inlineTitle, inlineTitle {
                            AnyView(title)
                        }
                    }
                    Spacer()
                }.background(.clear).frame(maxHeight: .infinity)
                
                HStack (alignment: .center) {
                    if let leftElement {
                        Button(action: {
                            if let leftAction {
                                leftAction() // Invoke the left action closure
                            }
                        }) {
                            AnyView(leftElement)
                        }
                    }
                    
                    Spacer()
                    
                    if let rightElement {
                        Button(action: {
                            if let rightAction {
                                rightAction() // Invoke the right action closure
                            }
                        }) {
                            AnyView(rightElement)
                        }
                    }
                }.frame(maxHeight: .infinity)
            }
            .frame(height: height)
            
            if let inlineTitle, !inlineTitle {
                if let title {
                    HStack {
                        AnyView(title)
                        Spacer()
                    }
                }
            }
        }
        .padding(.horizontal)
        .background(backgroundColor)
        .foregroundColor(foregroundColor)
    }
}




struct CustomNavigationBar_Preview_1: View {
    var body: some View {
        CustomNavigationBar(
            leftElement: Text("Back"),
            leftAction: {
                // Left Action
            },
            rightElement: Text("Save"),
            rightAction: {
                // Left Action
            },
            title: Text("Title"),
            backgroundColor: Color.clear,
            foregroundColor: Color.black).padding(0)
        
    }
}

struct CustomNavigationBar_Preview_2: View {
    var body: some View {
        CustomNavigationBar(
            leftElement: Text("Back"),
            rightElement: Text("Save"),
            title: Text("Title").font(.subheadline),
            backgroundColor: Color.black,
            foregroundColor: Color.white).padding(0)
    }
}

struct CustomNavigationBar_Preview_3: View {
    var body: some View {
        CustomNavigationBar(
            leftElement: Image(systemName: "arrowshape.backward.fill"),
            title: Text("Title")
            .frame(maxWidth: .infinity, alignment: .leading)
            .font(.largeTitle), 
            inlineTitle: false,
            backgroundColor: Color.blue,
            foregroundColor: Color.white).padding(0)
    }
}

struct CustomNavigationBar_Preview_4: View {
    var body: some View {
        CustomNavigationBar(
            leftElement: Text("Title")
                .frame(maxWidth: .infinity, alignment: .leading)
                .font(.largeTitle),
            rightElement: Text("Close"),
            backgroundColor: Color.red,
            foregroundColor: Color.white).padding(0)
    }
}

struct CustomNavigationBar_Preview_5: View {
    var body: some View {
        CustomNavigationBar(
            leftElement: Text("Title")
                .frame(maxWidth: .infinity, alignment: .leading)
                .font(.largeTitle),
            rightElement: Image(systemName: "xmark.circle").font(.largeTitle),
            backgroundColor: Color.green,
            foregroundColor: Color.white,
            height: 100).padding(0)
    }
}

#Preview {
    VStack (alignment: .leading) {
        CustomNavigationBar_Preview_1()
        CustomNavigationBar_Preview_2()
        CustomNavigationBar_Preview_3()
        CustomNavigationBar_Preview_4()
        CustomNavigationBar_Preview_5()
        Spacer()
    }.padding(0)
}

The above code is self-explanatory with the examples provided.
You can download the file from here: https://github.com/dipinkrishna/swiftui/blob/main/CustomNavigationBar.swift

Hope it helps!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.