I have MainView and where I have NavigationStack. I need to make it so that when I press the Search button, another view is shown and when I press the Cancel button, it is hidden again.
var body: some View {
NavigationStack {
if ($searchText.wrappedValue.isEmpty) {
ScrollView(.vertical, showsIndicators: true){
something()
}.navigationBarTitle("Summary")}
else { Text("Find: \(searchText)") }
if (showView==true) {
showSomethingView()
}
}
.searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always), prompt: "Look for something")
.onSubmit(of: .search) { showView=true }
}
I need to perform a search after the user clicks the Search button. At the same time there is no such thing as onCancel.
Related
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)
}
}
}
I have a ToolbarItemGroup with a navigation link and a button. With the current setup when I hit "Add" it goes to the AddNewTripView just fine but when I hit the back button (to return to the list view) it goes back to the previous view and then jumps right back to the AddNewTripView.
If I remove the Edit button it works fine. Is this a bug in SwiftUI or am I doing something wrong?
var body: some View {
ScrollView { }
.onAppear {
tripListViewModel.getAllTrips()
}
.navigationTitle("Trips")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItemGroup(placement: .navigationBarTrailing) {
NavigationLink(destination: AddNewTripView(repo: repo)) {
Text("Add")
}
Button(action: { isEditing.toggle() }) {
Text(isEditing ? "Done" : "Delete")
.foregroundColor(.primary)
}
}
}
}
I want to get an edit and add a button like the circled buttons shown in the image below. I need these buttons so that I can change the properties of the folders. How do I get this button to work when the default SwiftUI Edit button is clicked?
What I want:
(Before Edit button clicked)
(After Edit Button Clicked)
What I currently have:
(Before Edit button clicked)
(After Edit Button Clicked)
My code:
var body: some View {
ZStack {
List {
ForEach(searchResults, id: \.self.id) { dir in
Section(dir.title) {
ForEach(dir.getChildFolders(), id: \.self.id) { folder in
NavigationLink(destination: DirectoryView(directory: folder)) {
Label(folder.title, systemImage: "folder")
}
}
.onDelete(perform: { offsets in
dir.items.remove(atOffsets: offsets)
updateView.update()
})
.onMove(perform: { source, destination in
dir.items.move(fromOffsets: source, toOffset: destination)
updateView.update()
})
}
}
}
You need to display the button yourself.
First, ensure you have some #State var tracking whether Edit mode is toggled:
#State var editing: Bool = false
Then, in your body, show the circle button next to the NavigationLink if you are editing:
var body: some View {
ZStack {
List {
ForEach(searchResults, id: \.self.id) { dir in
Section(dir.title) {
ForEach(dir.getChildFolders(), id: \.self.id) { folder in
HStack {
NavigationLink(destination: DirectoryView(directory: folder)) {
Label(folder.title, systemImage: "folder")
}
if editing {
Spacer()
Button(action: {
// Perform circle button action here
}) {
Image(systemName: "ellipsis.circle")
}
}
}
}
.onDelete(perform: { offsets in
dir.items.remove(atOffsets: offsets)
updateView.update()
})
.onMove(perform: { source, destination in
dir.items.move(fromOffsets: source, toOffset: destination)
updateView.update()
})
}
}
}
}
}
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
}
}
}
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