Two NavigationBar Items appears twice in the second current view - swiftui

I have a current SwiftUI View with a Navigation Bar item . I created a Back Button on this current view so that the title is not inherited from the previous view (NEWSview) with list of news websites to navigate to the current view and clicking on the back button returns me to the previous view. This is sample code of the previous view screen how i did:
struct ContentView: View {
#ObservedObject var networkManager = NetworkManager()
var body: some View {
NavigationView {
List (networkManager.posts) { post in
NavigationLink (destination: DetailView(url: post.url) ) {
HStack {
Text(String(post.points))
Text(post.title)
}
}
}
.navigationBarTitle("News")
}
.onAppear {
DispatchQueue.main.async {
self.networkManager.fetchData()
}
}
}
}
This is the current screen view that is having the two buttons:
struct DetailView: View {
let url : String?
#Environment(\.presentationMode) private var mode
var body: some View {
WebView(urlString: url)
.navigationBarItems(leading:
Button(action: {
self.mode.wrappedValue.dismiss()
}, label: {
HStack(spacing: 10) {
Image(systemName: "chevron.left")
.resizable()
.frame(width: 10.0, height: 19.0)
.font(.headline)
Text("Back")
}
})
)
}
}
Now the issue is : The current screen NavBar has two buttons like this : one with news title and the back button (Picture attached) . I want only to remain with the Back Button on the current view that on click will navigate back to the previous root view . I thought what i did is right but missing something . If remove the entire code with the button in the current view , i will only see the "NEWS" navigation that on click will return me to the News View but i want a back title that should not be inherited from the news view .

Related

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

Splitup of Form Inline Navigation Bar Title

I created an entry form as an independent project with the navigation bar working great. I then copied the view to my overall project. In the process my inline navigation bar title split up leaving the Back button where it should be and creating a large space before displaying the title and the Save button (See photo below). There is a similar question at How to remove the default Navigation Bar space in SwiftUI NavigiationView but they are trying to remove the space in addition to the title from a List whereas I'm working with a form. Another question with large navigation bar space was due to a duplicate navigation bar title (Removing large amounts of whitespace in a SwiftUI subview). That is not the case here. Any ideas?
here is some of the code:
`struct entryView: View {
#EnvironmentObject var userData: UserData
#Environment(\.managedObjectContext) var viewContext // core data
. . .
var body: some View {
NavigationView {
Form {
// get entry date and time
Section {
HStack {
Image("iconCalendar24")
Spacer()
DatePicker("", selection: $entryDT, in: ...Date())
.datePickerStyle(CompactDatePickerStyle())
}
}
. . .
// select entry category
Section {
HStack {
Text("Select Category")
.font(Font.subheadline.bold())
Picker(selection: $entryCat, label: Text("")) {
ForEach(0 ..< self.categories.count) {
Text(self.categories[$0]).tag($0)
}
}
}
}
.navigationBarTitle(Text("Expense Entry"), displayMode: .inline)
.navigationBarItems(trailing:
Button(action: {
self.saveButton() // button pressed
}) {
Text ("Save")
}.disabled(moneyS.isEmpty)
)
}
}
}
}
Simulator view of the Expense Entry screen
It looks like you already have one NavigationView somewhere in parent view, so you don't need another one here.
Try to remove
struct entryView: View {
#EnvironmentObject var userData: UserData
#Environment(\.managedObjectContext) var viewContext // core data
. . .
var body: some View {
//NavigationView { // << this one !!
I texted out the whole view then slowly brought pieces in one at a time. It turns out the navigation bar return to inline format when I removed NavigationView { } from the view.
It is strange that the navigation bar displayed correctly in the standalone project but then failed when brought into the main project with other files / views.

SwiftUI NavigationBar Title not present as it is when ActionSheet is present

I have a problem regarding NagivationBarTitle.
I have a view (first view) from which I call another one (second view).
In the second view I have some photos which I can select. If no Images are selected the NavigationBar title is "Images". If I have images selected I have the title like "x Images selected".
If I have images selected I can press a button which will display an ActionSheet.
The problem is that when the action sheet is shown the title is going back to "Images".
How can I preserve the title in ActionSheet as it was before tapping ("x Images selected")?
Some example of code when action sheet is shown:
First View:
struct FirstView: View {
var body: some View {
VStack (alignment: .leading) {
List {
AnotherView(param: param)
.navigationBarItems(trailing:
NavigationLink(destination: SecondView()) {
Image(name: "search")
}
)
}
}
}
}
Second View:
struct SecondView: View {
#State private var imagesSelected: Int = 0
var body: some View {
VStack {
List {
// here is a grid of items. every time an item is clicked a
// counter in encreasing
when item clicked: imagesSelected++
}
.navigationBarTitle("\(self.imagesSelected) Files selected")
.actionSheet(isPresented: $showingActionSheet) {
ActionSheet(title: Text("Delete Images"), buttons: [
.destructive(Text("Delete")){
// Some action
},
.cancel()
])
}
}
}
}

How to Hide Keyboard in SwiftUI Form Containing Picker?

I have a SwiftUI Form that contains a Picker, a TextField, and a Text:
struct ContentView: View {
var body: some View {
Form {
Section {
Picker(selection: $selection, label: label) {
// Code to populate picker
}.pickerStyle(SegmentedPickerStyle())
HStack {
TextField(title, text: $text)
Text(text)
}
}
}
}
}
The code above results in the following UI:
I am able to easily select the second item in the picker, as shown below:
Below, you can see that I am able to initiate text entry by tapping on the TextField:
In order to dismiss the keyboard when the Picker value is updated, a Binding was added, which can be seen in the following code block:
Picker(selection: Binding(get: {
// Code to get selected segment
}, set: { (index) in
// Code to set selected segment
self.endEditing()
}), label: label) {
// Code to populate picker
}
The call to self.endEditing() is provided in the following method:
func endEditing() {
sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
The following screenshot displays that selecting a different segment of the Picker dismisses the keyboard:
Up to this point, everything works as expected. However, I would like to dismiss the keyboard when tapping anywhere outside of the TextField since I am unable to figure out how to dismiss the keyboard when dragging the Form's containing scroll view.
I attempted to add the following implementation to dismiss the keyboard when tapping on the Form:
Form {
Section {
// Picker
HStack {
// TextField
// Text
}
}
}.onTapGesture {
self.endEditing()
}
Below, the following two screenshot displays that the TextField is able to become the first responder and display the keyboard. The keyboard is then successfully dismissed when tapping outside of the TextField:
However, the keyboard will not dismiss when attempting to select a different segment of the `Picker. In fact, I cannot select a different segment, even after the keyboard has been dismissed. I presume that a different segment cannot be selected because the tap gesture attached to the form is preventing the selection.
The following screenshot shows the result of attempting to select the second value in the Picker while the keyboard is shown and the tap gesture is implemented:
What can I do to allow selections of the Picker's segments while allowing the keyboard to be dismissed when tapping outside of the TextField?
import SwiftUI
struct ContentView: View {
#State private var tipPercentage = 2
let tipPercentages = [10, 15, 20, 25, 0]
#State var text = ""
#State var isEdited = false
var body: some View {
Form {
Section {
Picker("Tip percentage", selection: $tipPercentage) {
ForEach(0 ..< tipPercentages.count) {
Text("\(self.tipPercentages[$0])%")
}
}
.pickerStyle(SegmentedPickerStyle())
HStack {
TextField("Amount", text: $text, onEditingChanged: { isEdited in
self.isEdited = isEdited
}).keyboardType(.numberPad)
}
}
}.gesture(TapGesture().onEnded({
UIApplication.shared.windows.first{$0.isKeyWindow }?.endEditing(true)
}), including: isEdited ? .all : .none)
}
}
Form's tap gesture (to finish editing by tap anywhere) is enabled only if text field isEdited == true
Once isEdited == false, your picker works as before.
You could place all of your code in an VStack{ code }, add a Spacer() to it and add the onTap to this VStack. This will allow you to dismiss the keyboard by clicking anywhere on the screen.
See code below:
import SwiftUI
struct ContentView: View {
#State private var text: String = "Test"
var body: some View {
VStack {
HStack {
TextField("Hello World", text: $text)
Spacer()
}
Spacer()
}
.background(Color.red)
.onTapGesture {
self.endEditing()
}
}
func endEditing() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}
Changing the background color of an HStack or VStack to red simplifies figuring out where the user may click to dismiss.
Copy and paste code for a ready to run example.

SwiftUI Splitview the DetailView not in Navigation?

I try to create a splitview in SwiftUI, and I have 2 issues
1. the Detail-View not showing in the navigation
2. if I go to Detail-View from master view it shows in navigation (Navigation top bar), but when it goes to next page, back button not work
struct MainView: View {
var body: some View {
NavigationView {
ListView()
DetailView()
}
}
}
struct ListView: View {
let menuItems = [MenuItem(name: "Login"),
MenuItem(name: "KS & Token"),
MenuItem(name: "Household & Domain"),
MenuItem(name: "Register")]
var body: some View {
VStack{
List{
ForEach(self.menuItems, id:\.id) { item in
NavigationLink(destination: LoginView(menuItem: item)){
Text(item.name)
}
}
}
Spacer()
}
.navigationBarTitle(Text("User Menu"))
}
}
the issue is:
1. DetailView() not showing Navigation top bar
2. in LoginView, when I go to next page with NavigationLink, the app does not show back button, and also add it by code, not help