Change Navigation Title of Picker in SwiftUI
Asked Answered
S

2

15

I'd like to set a navigation title when an user selected some option in Picker

Here is my selection model:

enum AppIcon: CaseIterable, Identifiable {

    var id: Self {
        return self
    }

    case `default`
    case ethereum
    case litecoin

    var name: String {
        switch self {
        case .default:
            return "Bitcoin"
        case .ethereum:
            return "Ethereum"
        case .litecoin:
            return "Litecoin"
        }
    }
}

and here is my view

struct ContentView: View {
    @State var icon: AppIcon = .default
    var body: some View {
        NavigationView {
            Form {
                Section {
                    Picker(selection: $icon, label: Text("Icon")) {
                        ForEach(AppIcon.allCases) { icon in
                            Text(icon.name).tag(icon)
                        }
                    }
                }
            }
            .navigationBarTitle("Appearance")
        }
    }
}

I want to get that behavior:

enter image description here

but I tried to put .navigationBarTitle("Title") after any close bracket and it doesn't work.

Shilashilha answered 10/10, 2019 at 10:34 Comment(0)
D
0

I have tried to solve issue.

struct ContentView: View {
    
    @State var icon: AppIcon = .default
    
    var body: some View {
        NavigationView {
            Form {
                Section {
                    Picker(selection: $icon, label: Text("Icon")) {
                        ForEach(AppIcon.allCases) { icon in
                            Text(icon.name).tag(icon)
                        }
                        .navigationBarTitle("Title") // for picker navigation title 
                    }
                    .navigationBarTitle("Appearance")
                }
            }
        }
    }
}
Dissent answered 10/10, 2019 at 11:2 Comment(6)
It works, thanks! So it's important where to write .navigationBarTitle(), but I still don’t understand how it works :)Shilashilha
Check out the following article: swiftui-lab.com/communicating-with-the-view-tree-part-1Dawndawna
this solution has 2 issues. 1) the title appears suddenly rather than sliding in with the view. 2) when you back out of this view using the back button the navigation bar title stays as "Title" rather than reverting to the "Appearance" title.Truong
Any solution to dissolve the issues mentioned by @Truong ?Pennington
With iOS 15 this is changing the navigation title of the view prior to presenting pickerInnumerable
@Truong ie it's completely useless but is the accepted answer and upvoted 6 times.Fall
D
1

The trick is to create a new view via a NavigationLink.
So show us the code!!!

This is the main View with a Form in a NavigationView.

struct ContentView: View {

    @ObservedObject private var viewModel: ViewModel

    init() {
        self.viewModel = ViewModel()
    }

    var body: some View {
        NavigationView {
            Form {
                PickerView(viewModel: viewModel)
            }
            .navigationTitle("Appearance")
        }
    }
}

I used a ViewModel to hold the data which the View is presenting. I guess it is possible to do it without.

class ViewModel: ObservableObject {
    @Published var icon: AppIcon = .default
}

In this struct the actual picker is defined. It is simulated with a list.

struct PickerView: View {

    @ObservedObject private var viewModel: ViewModel
    @State var presentSelectionView = false  // for getting back to main menu

    init(viewModel: ViewModel) {
        self.viewModel = viewModel
    }

    var body: some View {
        NavigationLink(isActive: $presentSelectionView) {
            picker()
                .navigationTitle("Title")
                .navigationBarTitleDisplayMode(.large)
        } label: {
            HStack {
                Text("Icon")
                Spacer()
                Text(viewModel.icon.name)
                    .foregroundColor(Color.gray)
            }
        }
    
    }

    private func picker() -> some View {
        List {
            ForEach(AppIcon.allCases, id: \.self) { icon in
                HStack {
                    Text(icon.name)
                    Spacer()
                    if icon == viewModel.icon  {
                        Image(systemName: "checkmark")
                            .foregroundColor(.accentColor)  // or any other color
                    }
                }
                .contentShape(Rectangle())  // whole line is tappable
                .onTapGesture {
                    self.viewModel.icon = icon
                    self.presentSelectionView = false
                }
            }
        }
        .listStyle(GroupedListStyle())
    }

}

I used the enum like it was given in the question.

In the end it looks like this:

main and picker screen

I have done this with XCode 13.1 and iOS 15.2

Depicture answered 22/12, 2021 at 9:36 Comment(1)
Worked like a charm. This should be the selected answer.Quillon
D
0

I have tried to solve issue.

struct ContentView: View {
    
    @State var icon: AppIcon = .default
    
    var body: some View {
        NavigationView {
            Form {
                Section {
                    Picker(selection: $icon, label: Text("Icon")) {
                        ForEach(AppIcon.allCases) { icon in
                            Text(icon.name).tag(icon)
                        }
                        .navigationBarTitle("Title") // for picker navigation title 
                    }
                    .navigationBarTitle("Appearance")
                }
            }
        }
    }
}
Dissent answered 10/10, 2019 at 11:2 Comment(6)
It works, thanks! So it's important where to write .navigationBarTitle(), but I still don’t understand how it works :)Shilashilha
Check out the following article: swiftui-lab.com/communicating-with-the-view-tree-part-1Dawndawna
this solution has 2 issues. 1) the title appears suddenly rather than sliding in with the view. 2) when you back out of this view using the back button the navigation bar title stays as "Title" rather than reverting to the "Appearance" title.Truong
Any solution to dissolve the issues mentioned by @Truong ?Pennington
With iOS 15 this is changing the navigation title of the view prior to presenting pickerInnumerable
@Truong ie it's completely useless but is the accepted answer and upvoted 6 times.Fall

© 2022 - 2024 — McMap. All rights reserved.