Hide Navigation Bar after NavigationLink is Tapped but keeping back button - swift

I have two different views, one with a NavigationView and another one that i want without NavigationView but since i put it in a NavigationLink I can still see it with a button to go back to the first view.
Here's the code:
struct MainView: View {
var body: some View {
NavigationView {
NavigationLink(destination: SecondView()) {
Text("Go to SecondView")
.navigationBarTitle("MainView")
}
}
}
struct SecondView: View {
var body: some View {
Text("This is the SecondView")
}
I want to hide the Navigation Bar in the Second View but leaving a button to go back. I don't know if i can keep the button that was already displayed in the Navigation Bar or should i make a new one...in this case how can I add one to go back to the previous view?

Related

SwiftUI NavigationView nested in PageTabView wrong aligned on first appear

The NavigationViews inside my PageTabView are wrong aligned on first appear.
When i scroll to another page on my PageTabView and go back to the first page, the alignment is correct.
The content of the navigationview (red) is beneath the navigationbar on first appear.
Image of first appearance of the NavigationView
Image of the second appearance of the NavigationView
struct ContentView: View {
var body: some View {
TabView {
ForEach(0..<3) { index in
NavigationView {
Color.red
.navigationTitle("\(index). Page")
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
.tabViewStyle(.page)
}
}
Edit:
I want to build the layout of the rooms tab in the apple home app in compact mode. Therefore the TabView in the code above gets wrapped in another tabview without the pagetabviewstyle modifier.
This works, but the same extracted problem in the code above happens.
var body: some View {
NavigationView {
TabView {
ForEach(0..<3) { index in
Color.red
.navigationTitle("\(index). Page")
}
}
.tabViewStyle(.page)
}
}
Just moved NavigationView outside, it fixed the problem

Navigation bar: "hide" title but keep it for the subsequent back button

In my app I have two SwiftUI views, let's call them View1 and View2. View1 is started as a UIHostingController and has a "Go to View2" button which pushes View2 on the navigation controller of the mentioned UIHostingController (no SwiftUI Navigation Links etc).
View1 has to display the navigation bar because it has a custom "Exit" button in the toolbar. View2 should show "<Back" navigation bar button which leads to the View1.
Problem:
If I set navigation bar title of the UIHostingController to "", then
there will be no "<Back" but "<".
If I set navigation bar title of the UIHostingController to
"Back", then after coming back View1 will show "Back" in the
middle of the navigation bar.
If I hide the navigation bar at first, then "Exit" button will not be
shown.
So, to sum up, what I need is:
View1 shows navigation bar only with the "Exit" toolbar button, no title.
View2 shows only "<Back" navigation bar button
How can I achieve it ?
Note: the whole navigation logic is done with UIKit. View1 notifies the view model which calls a delegate which pushes View2 on the navigation stack. There are no SwiftUI navigation links etc.
You might want consider a hidden Navigation Link so you get the push behaviour you are looking for. This will leave you with the following views;
struct View1: View {
#State private var isActive = false
var body: some View {
NavigationView {
VStack {
Button("Present") {
isActive = true
}
NavigationLink(destination: View2(), isActive: $isActive) {
EmptyView()
}.hidden()
}.toolbar(content: {
Button("Exit") {
print("Exit view")
}
})
}
}
}
struct View2: View {
var body: some View {
NavigationView {
Text("View 2")
}
}
}
Your first view will use the button to present view 2 through a push animation. Giving you the back button behaviour you are looking for. Your first view will have no title and a exit button in the toolbar in the right top corner.

Navigation between SwiftUI Views

I don't know how to navigate between views with buttons.
The only thing I've found online is detail view, but I don't want a back button in the top left corner. I want two independent views connected via two buttons one on the first and one on the second.
In addition, if I were to delete the button on the second view, I should be stuck there, with the only option to going back to the first view being crashing the app.
In storyboard I would just create a button with the action TouchUpInSide() and point to the preferred view controller.
Also do you think getting into SwiftUI is worth it when you are used to storyboard?
One of the solutions is to have a #Statevariable in the main view. This view will display one of the child views depending on the value of the #Statevariable:
struct ContentView: View {
#State var showView1 = false
var body: some View {
VStack {
if showView1 {
SomeView(showView: $showView1)
.background(Color.red)
} else {
SomeView(showView: $showView1)
.background(Color.green)
}
}
}
}
And you pass this variable to its child views where you can modify it:
struct SomeView: View {
#Binding var showView: Bool
var body: some View {
Button(action: {
self.showView.toggle()
}) {
Text("Switch View")
}
}
}
If you want to have more than two views you can make #State var showView1 to be an enum instead of a Bool.

SwiftUI navigationView within Modal 'pushing' view down

I currently have a modal view in SwiftUI that contains a series of NavigationLinks to different views. However, when I go to one of the other views it pushes all the content down leaving a empty forehead at the top of the view. How do I fix this?
I have included an example screenshot below.
To further clarify, there is a main view with a button that opens a Modal view. This modal contains a navigation view with a series of NavigationLink Buttons. When opening the navigation links within the modal, that is when the view is pushed down.
You have a large navigation bar, try to set navigationBar displayMode to .inline
.navigationBarTitle(Text(""), displayMode: .inline)
This probably happens because the view you push to from the NavigationView is also wrapped in a NavigationView.
struct SettingsView: View {
var body: some View {
NavigationView {
NavigationLink(destination: IAPView()) {
Text("In App Purchase")
}
}
}
}
You probably have this in the IAPView()
struct IAPView: View {
var body: some View {
NavigationView { <-- this is causing it
// your buttons here
}
}
}
You still have the default navigation bar space in your view. You need to add both these two view modifiers.
.navigationBarTitle("")
.navigationBarHidden(true)

SwiftUI Navigation through multiple screens

I'm a bit confused on how navigation works in SwiftUI. Does only the view starting the navigation need a NavigationView? I have one view with a NavigationView that has a NavigationLink to a second view. The second view then has a NavigationLink to a third and final view.
However, when my second view navigates to my third view, I get this message in the logs:
unbalanced calls to begin/end appearance transitions for <_TtGC7SwiftUI19UIHostingControllerVS_7AnyView_: 0x7f85d844bf90>.
I don't know if I'm handling navigation through multiple screens correctly and I'm getting some really odd behavior where pressing Next on my second screen takes me back to my first somehow...
//This is the link in my first view, my seconds link is the same except it does to my next step and the tag is different
NavigationLink(
destination: PasswordView(store: self.store),
tag: RegisterState.Step.password,
selection: .constant(store.value.step)
)
Navigation is a little bit tricky in SwiftUI, after creating one navigationview you don't need to create again in your 2nd or 3rd view. I am not sure how you creating it firstly. Here is an example how navigation is working.
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: SecondView()) {
Text("Show Second View")
}.navigationBarTitle("FirstView", displayMode: .inline)
}
}
}
}
struct SecondView: View {
var body: some View {
NavigationLink(destination: ThirdView()) {
Text("Show Third view")
}.navigationBarTitle("SecondView", displayMode: .inline)
}
}
struct ThirdView: View {
var body: some View {
Text("This is third view")
.navigationBarTitle("ThirdView", displayMode: .inline)
}
}