UPDATE: Resolved - This topic is just a beta bug.
I'm having a problem with the navigationBarTitle in SwiftUI.
I'm using a NavigationLink to go to a second view with a list. This view has a navigationBarTitle like the first view. But in the second view I can push the list behind the navigationBarTitle.
When I'm going from a third view back to the second the navigationBarTitle works as it should be.
Does anyone else having this problem? I'm using Xcode Version 11.0 GM (11A419c)
Here is the code:
struct ContentView: View {
private var line : [String] = ["Line 1", "Line 2", "Line 3"]
var body: some View {
NavigationView {
List {
ForEach(line, id: \.self) { item in
NavigationLink(destination: DetailView()) {
TestCell(lineName: item)
}
}
}
.navigationBarTitle("Main View")
}
}
}
struct TestCell: View {
let lineName: String
var body: some View {
Text(lineName)
}
}
struct DetailView: View {
var body: some View {
List() {
NavigationLink(destination: DetailDetailView()) {
Text("To the next view")
.foregroundColor(Color.red)
}
}
.navigationBarTitle("Detail View")
}
}
struct DetailDetailView: View {
var body: some View {
Text("Hello World!")
.navigationBarTitle("Detail Detail View")
}
}
Related
Not sure if this is a bug, but this is how to reproduce it in iOS 15 (didn't try lower versions)
In tab 1, scroll up (navigation bar will collapse properly)
Now, tap tab 2, but do not scroll the list
go back to tab 1. Now you should see navigation bar failed to collapse.
Source code:
struct TestNavigationView: View {
var body: some View {
NavigationView {
TabView {
LongList()
.tabItem({Text("Tab 1")})
LongList()
.tabItem({Text("Tab 2")})
}
.navigationTitle("Navigation Bar Test")
}
}
}
struct LongList: View {
var list = (1..<50).map {$0}
var body: some View {
List(list, id: \.self) { item in
NavigationLink {
Text("New view")
} label: {
Text("Item \(item)")
}
}
}
}
I have tried to twist the styles, but nothing worked. Any help would be appreciated! Thank you!
I believe that TabView and NavigationView are not good friends with each other.
If you avoid having the NavigationView around the TabView, you can achieve the same result. Move it to LongList, together with the .navigationTitle() modifier.
The following works fine:
struct TestNavigationView: View {
var body: some View {
// NavigationView {
TabView {
LongList(text: "One")
.tabItem({Text("Tab 1")})
LongList(text: "Two")
.tabItem({Text("Tab 2")})
}
// }
}
}
struct LongList: View {
var list = (1..<50).map {$0}
let text: String
var body: some View {
NavigationView {
List(list, id: \.self) { item in
NavigationLink {
Text("New view")
} label: {
Text("Item \(item) - \(text)")
}
}
.navigationTitle("Navigation Bar Test")
}
}
}
I'm new in SwiftUI and I have come to a weird behavior that is driving me nuts. I'm using the following code as an example:
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
ScrollView {
NavigationLink(
destination: NonEmojiView(),
label: { Text("NON-emoji view.") }
)
Spacer()
NavigationLink(
destination: EmojiView(),
label: { Text("Emoji view.") }
)
}
.navigationTitle("I love emojis")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct EmojiView: View {
var body: some View {
Text("Testing emojis in navigation titles.")
.navigationTitle("♥️")
}
}
struct NonEmojiView: View {
var body: some View {
Text("Testing emojis in navigation titles.")
.navigationTitle("Boring title")
}
}
When I run this app (iOS 14, XCode 12.2) and tap on the Emoji view (second navigation link), and then the "< Back" button in the navigation bar, the inline title style is shown in the navigation bar (image1) instead of the expected one (image 2). Any clue why? Anything am I doing wrong? Is that a SwiftUI bug? The only difference is the emoji in the title.
EDIT: As pointed out by Luffy, if the navigationTitle in ContentView contains an emoji too, it works well. May be related to the height of the title? More points for this to be a SwiftUI bug.
Thanks!!
If you add emoji in a ContentView's navBarTitle, it will work. If you remove it, then it won't. I think it's a SwiftUI bug.
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
ScrollView {
NavigationLink(
destination: NonEmojiView(),
label: { Text("NON-emoji view.") }
)
Spacer()
NavigationLink(
destination: EmojiView(),
label: { Text("Emoji view.") }
)
}
.navigationBarTitle(Text("I ❤️ emojis"), displayMode: .large) // <~ HERE
}
}
}
struct EmojiView: View {
let emoji = Image(systemName: "heart.fill")
var body: some View {
Text("Testing emojis in navigation titles.")
.navigationBarTitle(Text("❤️"), displayMode: .large)
}
}
struct NonEmojiView: View {
var body: some View {
Text("Testing emojis in navigation titles.")
.navigationBarTitle(Text("Boring title"), displayMode: .large)
}
}
I started to use SwiftUI after a couple years of UIKit.. This is not a piece of cake lol.
Alright, so I am trying to build an app that has a tab bar with 2 elements. Each Tab with contain a ViewController (View now) and they will be embedded in a NavigationController (NavigationView now)
The actual result is this
and I am expecting to have a nav bar with a title set to Home.
Could you explain me what I do wrong here? i followed the documentation and a couple tutorials, and I don't seem to do differently.
import SwiftUI
struct TabBarView: View {
var body: some View {
TabView() {
RedView()
.tabItem({
Image(systemName: "house.fill")
Text("Home")
})
.tag(0)
BlueView()
.tabItem({
Image(systemName: "dollarsign.square.fill")
Text("Trade")
})
.tag(1)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
TabBarView()
}
}
struct RedView: View {
var body: some View {
NavigationView {
List {
Text("test")
}
}
.navigationBarTitle("Home")
}
}
struct BlueView: View {
var body: some View {
NavigationView {
List {
Text("test2")
}
}
.navigationBarTitle("Trade")
}
}
This is the file that contains everything at the moment. Thanks in advance for any future help!
The .navigationBarTitle should be inside NavigationView
struct RedView: View {
var body: some View {
NavigationView {
List {
Text("test")
}
.navigationBarTitle("Home") // << here !!
}
}
}
I have lately been trying to make a tvOS app, but have run into the following rather annoying problem. I can't use navigation inside a TabView and still have the menu button on the remove take me back to the previous state.
struct TestView: View {
#State var selection : Int = 0
var body: some View {
TabView(selection: self.$selection) {
ExpView()
.tabItem {
HStack {
Image(systemName: "magnifyingglass")
Text("Explore")
}
}
.tag(0)
}
}
}
struct ExpView: View {
var body: some View {
NavigationView {
NavigationLink(destination: DetailView(title: "Hey")) {
Text("Detail")
}
}
}
}
struct DetailView: View {
var title : String
var body: some View {
VStack {
Text(title)
}
}
}
My question is: Is there any way to enable the menu button to go back to the previous view in the hierachy without dismissing the app completely?
You don't need to call dismiss on Menu it is called automatically for NavigationLink (so calling one more dismiss quits to main menu)
Here are fixed views. Tested with Xcode 11.4
struct ExploreView: View {
var body: some View {
NavigationView {
NavigationLink(destination: DetailView(title: "Hey")) {
Text("Detail")
}
}
}
}
struct DetailView: View {
var title : String
var body: some View {
VStack {
Text(title)
}
}
}
So I found a workaround for the issue.
If you place the navigationView outside the TabView and then use the following code it works:
struct TestView: View {
#State var selection : Int = 0
#State var hideNavigationBar : Bool
var body: some View {
NavigationView {
TabView(selection: self.$selection) {
ExpView(hideNavigationBar: self.$hideNavigationBar)
.tabItem {
HStack {
Image(systemName: "magnifyingglass")
Text("Explore")
}
}
.tag(0)
}
}
}
}
struct ExpView: View {
#Binding var hideNavigationBar : Bool
var body: some View {
NavigationLink(destination: DetailView(title: "Hey")) {
Text("Detail")
}.navigationBarTitle("")
.navigationBarHidden(self.hideNavigationBar)
.onAppear {
self.hideNavigationBar = true
}
}
}
struct DetailView: View {
var title : String
var body: some View {
VStack {
Text(title)
}
}
}
I have a modal sheet that is presented from my home view as such:
Button(action: {
...
}) {
...
}
.sheet(isPresented: ...) {
MySheetView()
}
In MySheetView, there is a NavigationView and a NavigationLink to push another view onto its view stack (while I'm on MySheetView screen and use the view inspector, there's only one UINavigationController associated with it which is what I expect).
However, as soon as I get to my next view that is presented from MySheetView using the NavigationLink, and I use the view hierarchy debugger, there are TWO UINavigationControllers on-top of each other. Note, this view does NOT have a NavigationView inside it, only MySheetView does.
Does anyone know what's going on here? I have a feeling this is causing some navigation bugs im experiencing. This can be easily reproduced in an example app with the same structure.
Ex:
// These are 3 separate SwiftUI files
struct ContentView: View {
#State var isPresented = false
var body: some View {
NavigationView {
Button(action: { self.isPresented = true }) {
Text("Press me")
}
.sheet(isPresented: $isPresented) {
ModalView()
}
}
}
}
struct ModalView: View {
var body: some View {
NavigationView {
NavigationLink(destination: FinalView()) {
Text("Go to final")
}
}
}
}
struct FinalView: View {
var body: some View {
Text("Hello, World!")
}
}
I don't observe the behaviour you described. Used Xcode 11.2. Probably you need to provide your code to find the reason.
Here is an example of using navigation views in main screen and sheet. (Note: removing navigation view in main screen does not affect one in sheet).
import SwiftUI
struct TestNavigationInSheet: View {
#State private var hasSheet = false
var body: some View {
NavigationView {
Button(action: {self.hasSheet = true }) {
Text("Show it")
}
.navigationBarTitle("Main")
.sheet(isPresented: $hasSheet) { self.sheetContent }
}
}
private var sheetContent: some View {
NavigationView {
VStack {
Text("Properties")
.navigationBarTitle("Sheet")
NavigationLink(destination: properties) {
Text("Go to Inspector")
}
}
}
}
private var properties: some View {
VStack {
Text("Inspector")
}
}
}
struct TestNavigationInSheet_Previews: PreviewProvider {
static var previews: some View {
TestNavigationInSheet()
}
}