Tikhonov Aleksandr
Tikhonov Aleksandr

Reputation: 14329

Change Navigation Title of Picker in SwiftUI

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.

Upvotes: 15

Views: 6811

Answers (2)

Laufwunder
Laufwunder

Reputation: 839

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

Upvotes: 1

Kishan Suthar
Kishan Suthar

Reputation: 658

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")
                }
            }
        }
    }
}

Upvotes: 0

Related Questions