SwiftUI can't change navigation bar right item for different segmented control view

With UIKit, we can easily change NavigationBar right item with segmented control. Like the sample code provide from Apple The first sample "Custom Right View"


When I try to use SwiftUI to achieve the same effect, I can't found a way to do it, any idea for this topic? Thanks in advance!


Answered by kevinyu in 658566022
I found a way to do the trick , but only for views with two layer hierarchy; if the segment control layout in the 3rd layer subview, it did not work.

Here's the two layer subview sample

Code Block
import SwiftUI
struct MainView: View {
    var body: some View {
        NavigationView {
            segview()
        }
    }
}
struct segview: View {
    let seg = ["s1", "s2", "s3"]
    @State private var selection = 0
    var body: some View {
        VStack {
            HStack {
                Picker("", selection: $selection) {
                    ForEach ( 0 ..< seg.count ) { index in
                        Text(seg[index])
                    }
                } .pickerStyle(SegmentedPickerStyle())
            }
            switch selection {
                case 0 : s1view()
                case 1: s2view()
                case 2: s3view()
                default: s1view()
            }
            Spacer()
        } .navigationBarItems(trailing: rightView(selection: selection))
        .navigationTitle("title")
          .navigationBarTitleDisplayMode(.inline)
    }
}
struct rightView:View {
    var selection:Int
    var body: some View {
        switch selection {
        case 0: Button("Add", action: {})
        case 1: Image(systemName: "car")
        default: Button("Default") {
        }
        }
    }
}

BUT, if the segview is embedded in tabview, like the following, the tricks won't work, it seems the .navigationBarItems modifier can only effect on the first subview of NavigationView, any subview deeper then the first subview, can't use the modifier

Code Block
import SwiftUI
struct MainView: View {
    var body: some View {
        NavigationView {
            MyTabview()
        }
    }
}
struct MyTabview: View {
    var body: some View {
        TabView  {
            segview().tabItem {
                Text("tab1")
            } // navigationBarItems can not work on this subview layer
            Text("tab2 view").tabItem {
                Text("tab2")
            }
        } .navigationTitle("Title") // navigationBarItems can work on this subview layer
    .navigationBarTitleDisplayMode(.inline)
    }
}

Any Suggestion?




Can you show an example code?
Accepted Answer
I found a way to do the trick , but only for views with two layer hierarchy; if the segment control layout in the 3rd layer subview, it did not work.

Here's the two layer subview sample

Code Block
import SwiftUI
struct MainView: View {
    var body: some View {
        NavigationView {
            segview()
        }
    }
}
struct segview: View {
    let seg = ["s1", "s2", "s3"]
    @State private var selection = 0
    var body: some View {
        VStack {
            HStack {
                Picker("", selection: $selection) {
                    ForEach ( 0 ..< seg.count ) { index in
                        Text(seg[index])
                    }
                } .pickerStyle(SegmentedPickerStyle())
            }
            switch selection {
                case 0 : s1view()
                case 1: s2view()
                case 2: s3view()
                default: s1view()
            }
            Spacer()
        } .navigationBarItems(trailing: rightView(selection: selection))
        .navigationTitle("title")
          .navigationBarTitleDisplayMode(.inline)
    }
}
struct rightView:View {
    var selection:Int
    var body: some View {
        switch selection {
        case 0: Button("Add", action: {})
        case 1: Image(systemName: "car")
        default: Button("Default") {
        }
        }
    }
}

BUT, if the segview is embedded in tabview, like the following, the tricks won't work, it seems the .navigationBarItems modifier can only effect on the first subview of NavigationView, any subview deeper then the first subview, can't use the modifier

Code Block
import SwiftUI
struct MainView: View {
    var body: some View {
        NavigationView {
            MyTabview()
        }
    }
}
struct MyTabview: View {
    var body: some View {
        TabView  {
            segview().tabItem {
                Text("tab1")
            } // navigationBarItems can not work on this subview layer
            Text("tab2 view").tabItem {
                Text("tab2")
            }
        } .navigationTitle("Title") // navigationBarItems can work on this subview layer
    .navigationBarTitleDisplayMode(.inline)
    }
}

Any Suggestion?




SwiftUI can't change navigation bar right item for different segmented control view
 
 
Q