Swiftui Double Navigation Bar

SwiftUI double navigation bar

Remove the NavigationView from SecondView.

The NavigationLink puts the second view inside the first views navigations view, so you do not need to put it inside a second one.

You can still update the title of the view from SecondView like so:

struct SecondView: View {
var body: some View {
Text("My View")
.navigationBarTitle("Second View")
}
}

SwiftUI - Two navigation bars

You are adding second NavigationView in RegisterView. That is the issue! because of using ContentView, for solving use MainView().

 struct RegisterView: View {
@ObservedObject var registerController = RegisterController()

@State private var showingRegistrationAlert = false

@State var navigateNext = false

let lightGreyColor = Color(red: 239.0/255.0, green: 243.0/255.0, blue: 244.0/255.0, opacity: 1.0)

var body: some View {
VStack {
VStack(alignment: .leading) {

Spacer()

NavigationLink(destination: MainView(), isActive:$navigateNext) { // <<: here
Text("")
}
Button(action: { if registerController.validateRegistration() {
showingRegistrationAlert.toggle()
}}) {
Text("Enviar registro")
}
.alert(isPresented: $showingRegistrationAlert) {
Alert(title: Text("Se registro correctamente"), dismissButton: .default(Text("Ok"), action: {
navigateNext.toggle()
}))

}
.padding()
.navigationBarTitle(Text("Registracion"), displayMode: .inline)

}
}

Double Navigation Bar SwiftUI

You don't need second NavigationView, there should be only one in navigation stack, ie

struct SecondView: View {
var body: some View {
// NavigationView { // << remove this one !!
VStack {
Text("This is Second View")
NavigationLink(destination: ThirdView()) {
Text("Show Third View")
}
}
.navigationBarTitle("Second View", displayMode: .inline)
// }
}
}

How can I avoid nested Navigation Bars in SwiftUI?

You should only have one NavigationView in your view hierarchy, as an ancestor of the menu view. You can then use NavigationLinks at any level of the hierarchy under that.

So, for example, your root view could be defined like this:

struct RootView: View {
var body: some View {
NavigationView {
MenuView()
.navigationBarItems(trailing: profileButton)
}
}

private var profileButton: some View {
Button(action: { }) {
Image(systemName: "person.crop.circle")
}
}
}

Then your menu view has NavigationLinks to the appropriate views:

struct MenuView: View {
var body: some View {
List {
link(icon: "calendar", label: "Appointments", destination: AppointmentListView())
link(icon: "list.bullet", label: "Work Order List", destination: WorkOrderListView())
link(icon: "rectangle.stack.person.crop", label: "Contacts", destination: ContactListView())
link(icon: "calendar", label: "My Calendar", destination: MyCalendarView())
}.navigationBarTitle(Text("Menu"), displayMode: .large)
}

private func link<Destination: View>(icon: String, label: String, destination: Destination) -> some View {
return NavigationLink(destination: destination) {
HStack {
Image(systemName: icon)
Text(label)
}
}
}
}

Your appointment list view also contains NavigationLinks to the appointment detail views:

struct AppointmentListView: View {
var body: some View {
List {
link(destination: AppointmentDetailView())
link(destination: AppointmentDetailView())
link(destination: AppointmentDetailView())
}.navigationBarTitle("Appointments")
}

private func link<Destination: View>(destination: Destination) -> some View {
NavigationLink(destination: destination) {
AppointmentView()
}
}
}

Result:

demo

How to create a shared navigation bar to inter-navigate among multiple views in SwiftUI?

You would use a TabView {...} to accomplish this. Effectively you instantiate your views inside of the TabView then add an item modifier to each view.

var body: some View {
TabView {
Text("A")
.tabItem { Text("A") }
Text("B")
.tabItem { Text("B") }
Text("C")
.tabItem { Text("C") }
}

init() {
UITabBar.appearance().backgroundColor = UIColor.red
}
}

What this code does: https://i.stack.imgur.com/CKBHm.gif

For added clarity, you can add any item you want to a TabView. It basically acts as a container for the views that you add.

struct ContentView: View {
var body: some View {
TabView {
FirstView()
.tabItem { Text("A") }
SecondView()
.tabItem { Text("B") }
ThirdView()
.tabItem { Text("C") }
}
}
}

struct FirstView: View {
var body: some View {
Text("A")
}
}

struct SecondView: View {
var body: some View {
Text("B")
}
}

struct ThirdView: View {
var body: some View {
Text("C")
}
}

Custom Tab Bar

This is a very simple case where we simply swap out the parent VStack{} based on the enum that we created. When it's first initialized this would set the .first page and that would be the one displayed. Anytime we change it with a button action located in the HStack{} the view is updated. This is especially useful if you want to add something more to the tab bar beyond text or an image. You could also add the selectedPage to an @EnvironmentObject to have control of those pages from anywhere in the app. It's especially useful when creating logins or landing pages, where you need to swap the navigation stack.

struct ContentView: View {
@State var selectedPage: SelectedPage = .first

var body: some View {
VStack {
VStack {
switch selectedPage {
case .first:
FirstView()
case .second:
SecondView()
case .third:
ThirdView()
}
}

Spacer()

HStack {
Button(action: { selectedPage = .first }, label: {
Text("A")
})

Spacer()

Button(action: { selectedPage = .second }, label: {
Text("B")
})

Spacer()

Button(action: { selectedPage = .third }, label: {
Text("C")
})
}.padding(.horizontal, 30)
}
}
}

enum SelectedPage {
case first, second, third
}

Hiding Navigation Bar in case of multiple Navigation Views in SwiftUI

If you want to hide navigation bar completely at third view here is possible approach. (Note: btw in one view hierarchy there must be only one NavigationView, so another one in ThirdView is not needed)

Tested with Xcode 11.4 / iOS 13.4

class HideBarViewModel: ObservableObject {
@Published var isHidden = false
}

struct FirstView: View {
@ObservedObject var vm = HideBarViewModel()
init() {
UINavigationBar.appearance().backgroundColor = UIColor.green
}

var body: some View {
NavigationView {
NavigationLink(destination: SecondView()) {
Text("Second View")
}.navigationBarTitle("First View")
.navigationBarHidden(vm.isHidden)
}.environmentObject(vm)
}
}

// Second View

struct SecondView: View {
var body: some View {
NavigationLink(destination: ThirdView()) {
Text("Third View")
}
}
}

// Third View

struct ThirdView: View {
@EnvironmentObject var vm: HideBarViewModel
var body: some View {
Text("Welcome")
.onAppear {
self.vm.isHidden = true
}
}
}

SwiftUI Navigation Bar Item with different destinations

You could add a function (in your view) that routes to the right destination (depending on the value of the "selection" property).

@ViewBuilder func addView() -> some View {
switch selection {
case .income: Text("Income destination")
case .expenses: Text("Expenses destination")
default: Rectangle()
}
}

Your NavigationLink calls this view builder :

NavigationLink("Add", destination: addView())


Related Topics



Leave a reply



Submit