NavigationView inside TabView not displaying correctly in landscape mode - ios

Navigation View inside Tabview
No issue in portrait mode
In landscape mode, navigation view and all subviews are "collapsed" into a top-level menu.
See screen shots below.
Is it normal behaviour?
Could not find any modifier to change this behaviour if it is normal.
Portrait mode
Landscape mode
Landscape mode after clicking top left menu
Test project showing issue:-
TabView {
ChartView().tabItem {
Label("Chart", systemImage: "chart.bar")
}
Page1View().tabItem {
Label("Received", systemImage: "tray.and.arrow.down.fill")
}
}
body of Page1View struct:-
var body: some View {
NavigationView {
VStack(spacing: 10) {
// ... removed for clarity
}
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Text("tbar1")
}
ToolbarItem(placement: .navigationBarTrailing) {
Text("tbar2")
}
ToolbarItem(placement: .navigationBarTrailing) {
Text("tbar3")
}
}
}
}

Found solution to this issue is that same as listed in:-
Swiftui NavigationView + TabView doesn't show navbar item
Added navigationViewStyle of .stack:-
NavigationView{
}
.navigationViewStyle(.stack)

Related

SwiftUI - Empty bottom bar after tapping NavigationLink

I have a NavigationView with a toolbar that contains a ToolBarItem with a .bottomBar placement and a search field. This NavigationView contains a ScrollView with content that exceeds the screen's vertical size, which means that the bottom bar has a background, as seen below:
When the user taps the "Root View" text element they navigate to a new view, in this case, just another text displaying "Detail View". The problem, however, is that the bottom toolbar's background remains in the screen instead of vanishing as expected. See the screenshot below:
This behavior is not seen if I remove the search bar or shrink the ScrollView's height to fit the vertical dimension of the device. I tried googling this issue to see if it was a known bug with a workaround but maybe I'm not searching the right keywords. How can I fix this issue?
Please see the bare minimum to replicate the issue below:
struct BugView: View {
#State var searchPattern: String = ""
var body: some View {
NavigationView {
ScrollView {
VStack {
NavigationLink(destination: Text("Detail View")) {
Text("Root View").foregroundColor(Color.blue)
}
Spacer()
Text("Root View Bottom").foregroundColor(Color.blue)
}.frame(maxWidth: .infinity, minHeight: 1000)
}
.searchable(text: self.$searchPattern, prompt: "Search Here")
.toolbar(content: {
ToolbarItem(placement: .bottomBar) {
Text("Toolbar text")
}
})
}
}
}
Setup:
XCode Version: 13.4.1
Simulator: iPhone 13
You can use the .toolbar(.hidden, for: .bottomBar) for the destination view as shown in the code below:
struct ContentView: View {
var body: some View {
NavigationView {
NavigationLink {
Text("Destination View")
} label: {
// hiding the toolbar for the destination view
Text("Root View").toolbar(.hidden, for: .bottomBar)
}
}.toolbar {
ToolbarItem(placement: .bottomBar) {
Text("Toolbar Text")
.background {
Color.gray
}
}
}
}
}

SwiftUI : How to get a Navigation Title aligned with Back Button

I'm trying to get the navigation title vertically aligned with the back button in a NavigationDetail view in SwiftUI. Here's what this looks like currently:
Below's my code for adding the Navigation Bar title to the view. How do I get it vertically aligned with the Back button?
var body: some View {
Text("My Detail View")
.navigationBarTitleDisplayMode(.inline)
VStack {
List {
ForEach(0..<layerSettings.count, id: \.self) { each in
...
}
}
If you need to draw "My Detail View" on the same line that the Back button, try to do like this:
NavigationView {
VStack() {
...
}
.navigationBarTitle(Text("My Detail View"),
displayMode: .inline)
}
Since navigationBarTitle(_:) is Deprecated. Use navigationTitle(_:) together with navigationBarTitleDisplayMode(_:) in iOS 14.0+
NavigationView {
VStack() {
...
}
.navigationTitle(Text("My Detail View"))
.navigationBarTitleDisplayMode(.inline)
}

iPad navigation automatically imposes slideout

I have a NavigationView with three NavigationLinks, on portrait iPhone, it works as expected where one taps a link, a new view is presented with a Back button. However on an iPad in landscape (which this app is designed for only), iOS forces a slideout menu from the left side instead of showing the three links on the view.
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
HStack {
NavigationLink(destination: ContentView()) {
Text("Item 1")
}
NavigationLink(destination: ContentViewC()) {
Text("Item 2")
}
NavigationLink(destination: ContentViewB()) {
Text("Item 3")
}
}
}
}
}
Any suggestions for overriding this behavior?
You can solve this issue by adding this
.navigationViewStyle(StackNavigationViewStyle())
to your NavigationView
NavigationView {
...
}.navigationViewStyle(StackNavigationViewStyle())
This will force it to render a standard stack (like you see on the phone) rather than defaulting to the split view layout.

Hide NavigationView bar in landscape mode and delay in hiding in SwiftUI

I'm still learning to SwiftUI and am playing with the NavigationView and I am able to hide the top navigation bar in portrait mode but have two issues.
1.) In landscape mode, there's a top bar that still sits on top of the view. Pulling it down brings down the notification center/settings
2.) After tapping the button in the view, it moves to the DetailView, but the top navigation bar is loaded briefly and then hides. How to stop the navigation from loading.
GIF of button to next view - the flow from tapping button to moving to next view to changing to landscape mode
Any feedback or approach is appreciated. Thanks!
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: DetailView()) {
Text("Hello World")
.fontWeight(.bold)
.font(.title)
.padding()
.background(Color.blue)
.cornerRadius(40)
.foregroundColor(.blue)
.padding(10)
.overlay(
RoundedRectangle(cornerRadius: 40)
)
}
.navigationBarTitle("", displayMode: .inline)
.navigationBarHidden(true)
.navigationBarBackButtonHidden(true)
//.edgesIgnoringSafeArea([.top, .bottom])
//.navigationViewStyle(StackNavigationViewStyle())
//.navigationViewStyle(DoubleColumnNavigationViewStyle())
}
}
.navigationBarTitle("", displayMode: .inline)
.navigationBarHidden(true)
.navigationBarBackButtonHidden(true)
//.statusBar(hidden: true)
}
}
I was also seeing the navigation bar shown briefly in the destination view before it disappeared. To fix that, I added the navigation bar properties to the destination view argument inside the NavigationLink call. For your example, it would look like this:
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: DetailView()
.navigationBarTitle("", displayMode: .inline)
.navigationBarHidden(true)
.navigationBarBackButtonHidden(true)
) { // The rest of your code...

Placing interactable views in front of a NavigationView's hidden navigation bar

I have a NavigationView with a NavigationButton inside of it, but I cannot get the NavigationButton to be at the top of the screen and still be able to be pressed, even though the navigation bar is hidden.
This code:
struct ContentView : View {
var body: some View {
NavigationView {
VStack {
NavigationButton(destination: Text("Button Clicked")) {
Text("Hello World")
.background(Color.yellow)
}
Spacer()
}
}
.navigationBarHidden(true)
}
}
Looks like , but I want it to look like .
I've tried adding a negative padding to the top of the VStack (with .padding([.top], -95), and it visually works, but then I can't interact with the button by tapping it (I think it is behind the hidden navigation bar). I've tried setting the VStack's zIndex to 10000 to solve that, but it still didn't work. Is there a way for me to move the button up to the top while still making sure that the button recognizes when it is being tapped?
Add a navigationBarTitle before hiding your navigation bar:
struct ContentView : View {
var body: some View {
NavigationView {
VStack {
NavigationButton(destination: Text("Button Clicked")) {
Text("Hello World")
.background(Color.yellow)
}
Spacer()
}
.navigationBarTitle(Text("Title")) // Add this line
.navigationBarHidden(true)
}
}
Add this modifier to your NavigationView edgesIgnoringSafeArea(.top).

Resources