Why NavigationView is shown inline when using emojis in navigationTitle in SwiftUI? - swift

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

Related

In SwiftUI, how can I put the navigation bar in the inner view?

In SwiftUI I want to implement the following view. But I have no idea how I can put the navigation bar in the white view inside. Because it is placed on top of the purple view by default.
import SwiftUI
struct ContentView: View {
var body: some View {
ZStack {
Color.purple
WhiteView() // the white view
.padding(.top, 30)
.padding()
}
.edgesIgnoringSafeArea(.all)
}
}
import SwiftUI
struct WhiteView: View {
var body: some View {
Color.white
.cornerRadius (12)
}
}
struct WhiteView_Previews: PreviewProvider {
static var previews: some View {
WhiteView()
}
}
Here is possible approach - use NavigationView over color view, so it takes frame of parent view but not full screen
Tested with Xcode 12.4 / iOS 14.4
struct WhiteView: View {
var body: some View {
Color.white
.overlay(NavigationView {
NavigationLink("Test", destination: Text("Details"))
})
.cornerRadius (12)
}
}
I took your code, stuck it in a NavigationView, added a .navigationTitle, .toolbar and ToolBarItem and this is the View I got:
Code:
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
ZStack {
Color.purple
WhiteView() // the white view
.padding(.top, 30)
.padding()
}
.edgesIgnoringSafeArea(.all)
.navigationTitle("Your Friends")
.toolbar {
ToolbarItem {
Text("Right Button")
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct WhiteView: View {
var body: some View {
Color.white
.cornerRadius (12)
}
}
What, exactly is your question/problem? Everything is in the white area.

SwiftUI TabView Animation

I am currently facing a pb on my app.
I would like to animate the insertion and removal of items that are controlled by SwiftUI TabView.
Here is the simplest view I can come with that reproduce the problem
struct ContentView: View {
#State private var selection: Int = 1
var body: some View {
TabView(selection: $selection.animation(),
content: {
Text("Tab Content 1")
.transition(.slide) //could be anything this is for example
.tabItem { Text("tab1") }.tag(1)
.onAppear() {print("testApp")}
.onDisappear(){print("testDis")}
Text("Tab Content 2")
.transition(.slide)
.tabItem { Text("tab2") }.tag(2)
})
}
}
Actually when hitting a tabItem. It switches instantly from "Tab Content 1" to "Tab Content 2" and I would like to animate it (not the tab item button the actuel tab content). The On Appear and onDisapear are corectly called as expected hence all transition should be triggered.
If someone has an idea to start working with I would be very happy
Thanks
1.with .transition() we only specify which transition should happen.
2.Transition occur (as expected), only when explicit animation occurs.
3.Animation occurs when change happened(State, Binding)
here is one of possible approaches.
struct ContentView: View {
#State private var selection: Int = 1
var body: some View {
TabView(selection: $selection,
content: {
ItemView(text:"1")
.tabItem { Text("tab1") }.tag(1)
ItemView(text: "2")
.tabItem { Text("tab2") }.tag(2)
})
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct ItemView: View {
let text: String
#State var hidden = true
var body: some View {
VStack {
if !hidden {
Text("Tab Content " + text)
.transition(.slide)
}
}
.onAppear() { withAnimation {
hidden = false
}}
.onDisappear(){hidden = true}
}
}

Variable 3-Column NavigationView SwiftUI

Problem
I would like to be able to change the number of columns in a Navigation View depending on the sidebar selection. i.e. Most views will have the desired 3-column layout (sidebar > list > detail) but one will have a two column layout (sidebar > detail). I tried to set this up directly in the top layer of the navigation view but this didn't change anything.
NavigationView{
SidebarView()
if selection != .explore {
ListView()
}
DetailView()
}
In the above example, if the selection is 'explore' there should only be a sidebar and a detail view.
Any ideas on how to achieve this?
Code to reproduce
I would want "searchView" to take up the full width. Meaning just a sidebar and search view should appear
Run on macOS or iPadOS
import SwiftUI
enum SidebarSelection {
case library
case notes
case search
}
struct ContentView: View {
#State var selection : SidebarSelection? = SidebarSelection.library
var body: some View {
NavigationView {
List {
NavigationLink(destination: ListView(), tag: SidebarSelection.library, selection: $selection){
Label("Library", systemImage: "book")
}
.tag(SidebarSelection.library)
NavigationLink(destination: ListView(), tag: SidebarSelection.notes, selection: $selection){
Label("Notes", systemImage: "doc.text")
}
.tag(SidebarSelection.notes)
NavigationLink(destination: SearchView(), tag: SidebarSelection.search, selection: $selection){
Label("Search", systemImage: "magnifyingglass")
}
.tag(SidebarSelection.search)
}
.listStyle(SidebarListStyle())
Text("List View")
if selection != .search {
Text("Detail View")
}
}
}
}
struct ListView: View {
var body: some View{
List {
ForEach(0..<10){ index in
NavigationLink(destination: Text("DetailView: \(index)")){
Text("Link to \(index) detail view")
}
}
}
}
}
struct SearchView: View {
var body: some View {
Text("Full width search view")
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
What you can do is quite easy actually, to achieve this, you just have to be bit more specific for SwiftUI and use the #ViewBuilder property wrapper.
struct ContentView: View {
#ViewBuilder
var body: some View {
if(twoColumns == true){
NavigationView{
SidebarView()
DetailView()
}
} else {
NavigationView{
SidebarView()
ListView()
DetailView()
}
}
}
}

SwiftUI TabView + NavigationView navbar doesn't show up

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 !!
}
}
}

Q: SwiftUI - navigationBarTitle transparent error

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