Search code examples
iosswiftswiftuibadgenavigationbaritems

How can I add a badge to a leading navigationBarItems in SwiftUI and iOS 14?


How can I add a badge to navigationBarItems in SwiftUI and iOS 14?

I cannot find anything on the net...

I want for example add a badge over the leading navigationBarItems:

var body: some View {
    NavigationView {
        ZStack {
            VStack(spacing: 0) {
                Text("Peanut")
                    .padding(-10)
                    .navigationBarTitle(Text("HomeTitle"), displayMode: .inline)
                    .navigationBarItems(leading:
                        HStack {
                            NavigationLink(destination: Notifications()) {
                                Image(systemName: "bell")
                                    .font(.system(size: 20))
                            }.foregroundColor(.white)
                        }, trailing:
                        HStack {
                            NavigationLink(destination: Settings()) {
                                Image(systemName: "gearshape")
                                    .font(.system(size: 20))
                            }.foregroundColor(.white)
                        })
            }
        }
    }
}

Solution

  • You can create a custom Badge view:

    struct Badge: View {
        let count: Int
    
        var body: some View {
            ZStack(alignment: .topTrailing) {
                Color.clear
                Text(String(count))
                    .font(.system(size: 16))
                    .padding(5)
                    .background(Color.red)
                    .clipShape(Circle())
                    // custom positioning in the top-right corner
                    .alignmentGuide(.top) { $0[.bottom] }
                    .alignmentGuide(.trailing) { $0[.trailing] - $0.width * 0.25 }
            }
        }
    }
    

    and use it as an overlay:

    struct ContentView: View {
        var body: some View {
            NavigationView {
                ZStack {
                    VStack(spacing: 0) {
                        Text("Peanut")
                            .padding(-10)
                            .navigationBarTitle(Text("HomeTitle"), displayMode: .inline)
                            .navigationBarItems(leading: leadingBarItems)
                    }
                }
            }
        }
    
        var leadingBarItems: some View {
            NavigationLink(destination: Text("Notifications")) {
                Image(systemName: "bell")
                    .font(.system(size: 20))
            }
            .foregroundColor(.primary)
            .padding(5)
            .overlay(Badge(count: 3))
        }
    }
    

    enter image description here

    Note

    The badge view uses alignment guides for positioning. For more information see: