SwiftUI: Back button disappears when clicked on NavigationLink - swiftui

I'm trying to add a NavigationLink at the top of the screen, but once I click it, it prompts me to the result and the Back button disappears.
SwiftUI Code:
NavigationView {
VStack {
NavigationLink (destination: Text("COOL")) {
Text("COOL")
}
Spacer()
}
.navigationBarHidden(true)
.navigationBarTitle(Text("Home"))
//.edgesIgnoringSafeArea([.top, .bottom])
}
The back button disappears after clicking on the NavigationLink: https://gyazo.com/9d39936c849f570a05687e41096ddeca

There is some glitch IMHO, when you use both .navigationBarHidden(true) and .navigationBarTitle(Text("Some text)). If you remove the last one, back button works as usual. Nevertheless I tried to return back button in your code snippet. It still has glitch while returning to first view, but back button don't disappear. I hope it will help and you will go further from here:
struct NotHiddenBackButton: View {
#State var hiddingNavBar = true
#State var goToSecondView = false
var body: some View {
NavigationView {
NavigationLink(destination: ViewWithBackButton(hiddingNavBar: $hiddingNavBar), isActive: $goToSecondView) {
VStack {
Text("COOL")
.onTapGesture {
self.hiddingNavBar = false
self.goToSecondView = true
}
Spacer()
}
}
.navigationBarHidden(hiddingNavBar)
.navigationBarTitle(Text("Home"))
}
}
}
struct ViewWithBackButton: View {
#Binding var hiddingNavBar: Bool
var body: some View {
Text("Second view")
.navigationBarTitle("Second view")
.onDisappear() {
self.hiddingNavBar = true
}
}
}

I believe this was a bug that has now been fixed in iOS 14

Related

How hide navigation bar always back from any view directly using NavigationView?

I am using xcode-14.2 & minimum target version 14. I have three views ContentView, Welcome & `FundTransfer. Here is my case.
ContentView - Load first view & navigationBarHidden is working. When Welcome page button click it goes to Welcome page
Welcome view - When Fund Transfer button is clicked, it goes to FundTransfer view
FundTransfer - when Log out button is clicked, it goes to ContentView
It goeslike: ContentView-> FundTransfer-> ContentView
Problem: When it goes from FundTransfer view to ContentView it shows navigationBar. That means when back from FundTransfer view to ContentView shows navigationBar which was hidden at the first.
How do I hide navigation bar always back from any view directly to ContentView?
Here is my code:
ContentView:
struct ContentView: View {
#State private var showWelcome = false
#State var isNavigationBarHidden: Bool = true
var body: some View {
NavigationView {
VStack {
ScrollView {
VStack(alignment: .customCenter,spacing: 0){
VStack {
SubmitButton(action: {
self.showWelcome = true
}) {
Text("Welcome page")
}
}
NavigationLink(destination: Welcome(), isActive: $showWelcome) { EmptyView() }
}
}
}
.navigationBarTitle("") //this must be empty
.navigationBarHidden(true)
.navigationBarBackButtonHidden(true)
}
}
}
Welcome View:
struct Welcome: View {
#State private var showFundTransfer = false
#Environment(\.presentationMode) var presentationMode
var body: some View {
VStack {
ScrollView {
VStack(alignment: .customCenter,spacing: 0){
VStack {
SubmitButton(action: {
showFundTransfer = true
}) {
Text("Fund Transfer")
}
}
NavigationLink(destination: FundTransfer(), isActive: $showFundTransfer) { EmptyView() }
}
}
.navigationBarHidden(true)
}
}
}
FundTransfer View:
struct FundTransfer: View {
#State var isNavigationBarHidden: Bool = true
#State private var logon = false
var body: some View {
VStack {
ScrollView {
VStack(alignment: .customCenter,spacing: 0){
SubmitButton(action: {
self.logon = true
}) {
Text("Log out")
}
}
}
NavigationLink(destination: ApplicationSwitcher(), isActive: $logon) { EmptyView() }.opacity(0)
}
.navigationBarHidden(true)
}
}
Please help me..
Add .navigationBarHidden(true) in NavigationLink also for eg:
NavigationLink(destination: ApplicationSwitcher()
.navigationBarHidden(true), isActive: $logon) { EmptyView() }.opacity(0)
In ContentView add "navigationBarHidden(true)" after the closure of NavigationView instead of VStack as mentioned below:
NavigationView {
...
}.navigationBarTitle("")
.navigationBarHidden(true)
.navigationBarBackButtonHidden(true)

SwiftUI toolbar .bottomBar button doesn't trigger when user configures accessibility1 size or larger

How can I accommodate user accessibility sizes with a bottomBar button?
With accessibility1 or larger user-configured in iOS, a bottomBar button fails to trigger. Smaller font sizes work. Configuring the toolbar placement to .navigation works.
Details: Navigate from ContentView > FirstView > SecondView, then back to the FirstView via the "Goodbye" bottomBar button displays the FirstView. Then FirstView's "Goodbye" button does not trigger. There is a user-workaround: in this situation, scroll the FirstView down to hide the Goodbye button, release, it returns, then press and it works. Code is below.
struct ContentView: View {
#State var showFirstView: Bool = false
var body: some View {
NavigationStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, world!")
Button("First View") { showFirstView = true }
}
.sheet(isPresented: $showFirstView) {
FirstView()
}
}
struct FirstView: View {
#Environment(\.dismiss) var dismiss
#State var showSecondView: Bool = false
var body: some View {
NavigationStack {
VStack {
Text("First View")
Button("Second View") { showSecondView = true }
}
.toolbar {
// On return from SecondView with accessibility1
// or large text size configured, the button below
// does not trigger (even with a programmatically limited
// font size via .dynamicTypeSize).
// However, scroll the view down slightly to hide the button,
// let it return on screen, then the Goodbye button works.
ToolbarItem(placement: .bottomBar) {
Button("Goodbye") { dismiss() }
}
}
}
.sheet(isPresented: $showSecondView) {
SecondView()
}
}
struct SecondView: View {
#Environment(\.dismiss) var dismiss
var body: some View {
NavigationStack {
VStack { Text("Second View") }
.toolbar {
ToolbarItem(placement: .bottomBar) {
Button("Goodbye") { dismiss() }
}
}
}
}
The technique #Asperi shared in the post, StackOverflow Toolbar disappears when going back, resolves my problem. See Update (1), Update (2), and Update (3) below.
struct FirstView: View {
#Environment(\.dismiss) var dismiss
#State var showSecondView: Bool = false
#State private var refresh = UUID() // <- Update (1)
var body: some View {
NavigationStack {
VStack {
Text("First View")
Button("Second View") { showSecondView = true }
}
.toolbar {
// On return from SecondView with accessibility1
// or larger text size configured, the button below
// does not trigger (even with a programmatically limited
// font size via .dynamicTypeSize).
// However, scroll the view down slightly to hide the button,
// let it return on screen, then the Goodbye button works.
// Or, change placement to .navigation and it works as expected.
ToolbarItem(placement: .bottomBar) {
Button("Goodbye") { dismiss() }
}
}.id(refresh) // <- Update (2)
}
.sheet(isPresented: $showSecondView) {
SecondView()
.onDisappear { refresh = UUID() } // <- Update (3)
}
}
}

SWIFTUI Button or NavigationLink?

I have a button called "save" that saves the user inputs.
But, I want to make it like, if the user tap on Button "Save", then the screen automatically goes back to the previous view. Can I do that by just adding a code to an action in Button? or do I have to use NavigationLink instead of Button?
Button(action: {
let title = shortcutTitle
currentShortcutTitle = title
UserDefaults.standard.set(title, forKey: "title")
}, label: {
Text("Save")
.padding()
.frame(width: 120, height: 80)
.border(Color.black)
}) //: Button - save
If you're just trying to go back to the previous view and already inside a NavigationView stack, you can use #Environment(\.presentationMode):
struct ContentView: View {
var body: some View {
NavigationView {
NavigationLink(destination: Screen2()) {
Text("Go to screen 2")
}
}.navigationViewStyle(StackNavigationViewStyle())
}
}
struct Screen2 : View {
#Environment(\.presentationMode) var presentationMode //<-- Here
var body: some View {
Button("Dismiss") {
presentationMode.wrappedValue.dismiss() //<-- Here
}
}
}

SwiftUI .popover dismiss won't work after List row being removed

I have a SwiftUI List with rows that contain a thumb. When clicked, this thumb opens a popover with a larger version of the image.
The problem I'm facing is that when a row, with its popover open, is removed from the list, the popover is left open and with no way of closing it, ending up with an unusable UI.
My goal would be to have the popover closed automatically when the row is removed from the list.
Following is a stripped version of the row's body. I'm using a Button because is more reliable than the onTapGesture event.
#State private var showPopover: Bool = false
var body: some View {
Button(action: { self.showPopover = true }) {
Image(systemName: "photo")
.onDisappear { self.showPopover = false}
}
.popover(isPresented: $showPopover, arrowEdge: .leading) {
Image(systemName: "photo")
}
}
You use this:
for dismiss, swipe down or tap on Back button! (I guarantee it is going dismiss)100%
import SwiftUI
struct ContentView: View {
#State private var showModalView: Bool = false
var body: some View {
VStack
{
Button("showModalView") {showModalView.toggle()}
}
.sheet(isPresented: $showModalView, content: {
ZStack
{
Color.red
.ignoresSafeArea()
Button("← Back"){showModalView.toggle()}.foregroundColor(Color.black)
}
})
}
}

Using SwiftUI, we installed a Button in the List. Why does the modal disappear when I tap the button to display the modal and then close it again?

I am now learning to create a sample code for SwiftUI using the official version of Xcode11.
I wrote a simple code to show and hide modal.
This code adds a button to the list and displays a modal.
Strangely, however, the modal no longer appears when the button is tapped again after closing.
Is there a reason for this or any solution?
Occurs when there is a button in the list, but if you delete only the list from the code, the modal can be displayed as many times as you like.
This is the code that causes the bug.
struct ContentView: View {
#State var show_modal = false
var body: some View {
List {
Button(action: {
print("Button Pushed")
self.show_modal = true
}) {
Text("Show Modal")
}.sheet(isPresented: self.$show_modal, onDismiss: {
print("dismiss")
}) {
ModalView()
}
}
}
}
This is a code that does not cause a bug.
struct ContentView: View {
#State var show_modal = false
var body: some View {
Button(action: {
print("Button Pushed")
self.show_modal = true
}) {
Text("Show Modal")
}.sheet(isPresented: self.$show_modal, onDismiss: {
print("dismiss")
}) {
ModalView()
}
}
}
The only difference is whether or not there is a List.
The ModalView code is below.
struct ModalView: View {
// 1. Add the environment variable
#Environment(\.presentationMode) var presentationMode
var body: some View {
// 2. Embed Text in a VStack
VStack {
// 3. Add a button with the following action
Button(action: {
print("dismisses form")
self.presentationMode.wrappedValue.dismiss()
}) {
Text("Dismiss")
}.padding(.bottom, 50)
Text("This is a modal")
}
}
}
When breakpoint is set, print ("Button Pushed") is called every time, but ModalView of .sheet is not called, and naturally the body of ModalView class is not called.
I think the issue is that your .sheet is not on the List itself but on the Button in your code that causes the bug.
Try this instead:
struct ContentView: View {
#State var show_modal = false
var body: some View {
List {
Button(action: {
print("Button Pushed")
self.show_modal = true
}) {
Text("Show Modal")
}
}.sheet(isPresented: self.$show_modal, onDismiss: {
print("dismiss")
}) {
ModalView()
}
}
}