Search code examples
swiftswiftuinavigationbarpickernavigationview

Adding Segmented Style Picker to SwiftUI's NavigationView


The question is as simple as in the title. I am trying to put a Picker which has the style of SegmentedPickerStyle to NavigationBar in SwiftUI. It is just like the native Phone application's history page. The image is below

enter image description here

I have looked for Google and Github for example projects, libraries or any tutorials and no luck. I think if nativa apps and WhatsApp for example has it, then it should be possible. Any help would be appreciated.


Solution

  • You can put a Picker directly into .navigationBarItems.

    enter image description here

    The only trouble I'm having is getting the Picker to be centered. (Just to show that a Picker can indeed be in the Navigation Bar I put together a kind of hacky solution with frame and Geometry Reader. You'll need to find a proper solution to centering.)

    struct ContentView: View {
        @State private var choices = ["All", "Missed"]
        @State private var choice = 0
    
        @State private var contacts = [("Anna Lisa Moreno", "9:40 AM"), ("Justin Shumaker", "9:35 AM")]
    
        var body: some View {
            GeometryReader { geometry in
                NavigationView {
                    List {
                        ForEach(self.contacts, id: \.self.0) { (contact, time) in
                            ContactView(name: contact, time: time)
                        }
                        .onDelete(perform: self.deleteItems)
                    }
                    .navigationBarTitle("Recents")
                    .navigationBarItems(
                        leading:
                        HStack {
                            Button("Clear") {
                                // do stuff
                            }
                            Picker(selection: self.$choice, label: Text("Pick One")) {
                                ForEach(0 ..< self.choices.count) {
                                    Text(self.choices[$0])
                                }
                            }
                            .frame(width: 130)
                            .pickerStyle(SegmentedPickerStyle())
                                .padding(.leading, (geometry.size.width / 2.0) - 130)
                        },
                    trailing: EditButton())
                }
            }
        }
    
        func deleteItems(at offsets: IndexSet) {
            contacts.remove(atOffsets: offsets)
        }
    
    }
    
    struct ContactView: View {
        var name: String
        var time: String
    
        var body: some View {
            HStack {
                VStack {
                    Image(systemName: "phone.fill.arrow.up.right")
                    .font(.headline)
                    .foregroundColor(.secondary)
                    Text("")
                }
                VStack(alignment: .leading) {
                    Text(self.name)
                        .font(.headline)
                    Text("iPhone")
                        .foregroundColor(.secondary)
                }
                Spacer()
                Text(self.time)
                    .foregroundColor(.secondary)
            }
        }
    }