Updating SwiftUI navigation bar title - ios

I have a Form view that sets the navigation bar title to "Settings" and a Picker view inside the Form view that sets the navigation bar title to "Options".
When navigating to Picker view, the navigation bar title does not get set to "Options", but the back button text does. Also, when navigating back to Form view, the navigation bar title is changed to "Options".
How can I have the navigation bar title be "Settings" while on Form view and "Options" while on Picker view? Thanks!
var body: some View {
NavigationView {
Form {
Picker(selection: $currentSelection, label: Text("Options")) {
ForEach(0 ..< options.count) {
Text(options[$0])
}
}
.navigationBarTitle("Options", displayMode: .inline)
}
.navigationBarTitle("Settings", displayMode: .inline)
}
}

Put navigation title modifier inside Picker. Also as same Text view from Picker item is used to present selection in Form we need to make Options title conditional.
Here is a demo of approach. Tested with Xcode 12.4 / iOS 14.4
Form {
Picker(selection: $currentSelection, label: Text("Options")) {
ForEach(0 ..< options.count) {
if $0 != currentSelection {
Text(options[$0])
.navigationBarTitle("Options", displayMode: .inline)
} else {
Text(options[$0])
}
}
}
}
.navigationBarTitle("Settings", displayMode: .inline)

Related

SwiftUI : How to get a Navigation Title aligned with Back Button

I'm trying to get the navigation title vertically aligned with the back button in a NavigationDetail view in SwiftUI. Here's what this looks like currently:
Below's my code for adding the Navigation Bar title to the view. How do I get it vertically aligned with the Back button?
var body: some View {
Text("My Detail View")
.navigationBarTitleDisplayMode(.inline)
VStack {
List {
ForEach(0..<layerSettings.count, id: \.self) { each in
...
}
}
If you need to draw "My Detail View" on the same line that the Back button, try to do like this:
NavigationView {
VStack() {
...
}
.navigationBarTitle(Text("My Detail View"),
displayMode: .inline)
}
Since navigationBarTitle(_:) is Deprecated. Use navigationTitle(_:) together with navigationBarTitleDisplayMode(_:) in iOS 14.0+
NavigationView {
VStack() {
...
}
.navigationTitle(Text("My Detail View"))
.navigationBarTitleDisplayMode(.inline)
}

NavigationBar with Custom Back Text but no NavigationBarTitle

I want to hide the navigationbarTitle for my views, but keep a custom value for the back button in the child views. So the NavigationBar should be visible in every screen, but should not have a title. But i want to change the text 'Back' to a custom text.
NavigationLink {
SomeChildView()
} label: {
SomeView()
}.navigationBarTitle("Text for back button in child view")
If I set the title on the NavigationLink this gives me my custom back button text but also displays the title in the Parent View.
You can achieve what you need by using the environment value of presentationMode to dismiss the screen you are in by code, and for changing the back button label and style you can simply do
hide the back button by using .navigationBarBackButtonHidden(true) modifier
use toolbar and toolbarItem to add your custom back button to the NavigationBar
here an example of how you can use it
// FirstScreen
struct ContentView: View {
var body: some View {
NavigationView {
NavigationLink {
SecondScreen()
} label: {
Text("Go To Second Screen")
}
}
}
}
// SecondScreen
struct SecondScreen: View {
#Environment(\.presentationMode) var presentationMode
var body: some View {
Text("Second Screen")
.navigationBarBackButtonHidden(true)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button {
presentationMode.wrappedValue.dismiss()
} label: {
Label("Custom Back Button", systemImage: "command")
.labelStyle(.titleAndIcon)
}
}
}
}
}

Add accessory view below navigation bar title in SwiftUI

I’m trying to add an accessory view embedded in a navigation bar below the title, which can be seen in the default iOS calendar app (the “s m t w t f s” row) or the GitHub mobile app:
And I’d like it to work along with the large title style navigation bar like the GH mobile.
LazyVStack’s pinnedView with a section header almost work, but I can’t get the background color to make it seemless with the navigation bar, even with the ultraThinMaterial. It also leaves the divider line between the pinned view and the bar.
Is there a way to achieve this layout?
Solutions in SwiftUI, SwiftUI+Introspect, and UIKit are all welcome!
Have you tried setting a .safeAreaInset view? This will have the stickiness you're looking for, and items in the "main" part of the view will take its height into account when rendering, so won't get obscured.
Here's a quick example I knocked up:
struct ContentView: View {
var body: some View {
NavigationView {
List {
ForEach(0 ..< 30) { item in
Text("Hello, world!")
}
}
.navigationTitle("Accessory View")
.safeAreaInset(edge: .top) {
AccessoryView()
}
}
}
}
struct AccessoryView: View {
var body: some View {
HStack {
Button("Button") { }
Button("Button") { }
Button("Button") { }
Spacer()
}
.padding()
.background(Color(uiColor: .systemGroupedBackground))
.buttonStyle(.bordered)
.controlSize(.mini)
}
}
You have to give the view a background otherwise it'll be transparent – but that background will (as long as it's a colour or a material) automatically extend into the navigation bar itself. Here's a GIF of the above code in action, where I've set the background to match the grouped list's background:
It's not perfect, especially as it looks distinct from the nav bar on scroll, but it might be useable for you?
Another idea is to replace the navigation bar with a custom one like this:
{
...
}
.safeAreaInset(edge: .top) {
VStack(alignment: .leading, spacing: 8) {
HStack() {
Button {
presentationMode.wrappedValue.dismiss()
} label: {
Image(systemName: "chevron.backward")
}
Spacer()
Text(navigationTitle).font(.title2).bold()
.multilineTextAlignment(.center)
.foregroundColor(.accentColor)
.frame(maxWidth: .infinity)
Spacer()
}
HStack {
Button("Button") { }
Button("Button") { }
Button("Button") { }
Spacer()
}
}
.padding()
.background(
.bar
)
}
You will also have to set:
.navigationBarBackButtonHidden(true)
and do not set a navigation title:
// .navigationTitle("....")

how to hide navigation bar on particular screen in SwiftUI?

I am navigating from one screen to another on previous screen i am hiding navigation bar but on second screen I want to show navigation bar but in mu case its hiding on second screen also.
navigation bar hidden on first screen as
.navigationBarHidden(true)
How can i show navigation bar on second screen? (I am NOT using navigation view on either screen)
My First parent screen has
NavigationView {
//design
}
.navigationBarTitle("ABCScreen", displayMode: .inline)
.navigationViewStyle(StackNavigationViewStyle())
Thank you for help.
The possible approach to hide navigation bar in root view and show in child subviews.
struct FirstNavigationView: View {
#State private var hideBar = true // << hide state
var body: some View {
NavigationView {
VStack {
Text("FirstView")
Divider()
NavigationLink("Goto Child", destination: NextChildView(index: 1))
.simultaneousGesture(TapGesture().onEnded {
self.hideBar = false // << show
})
}
.navigationBarHidden(hideBar)
// .navigationBarTitle("Back to Root") // << choice
.onAppear {
self.hideBar = true // << hide on back
}
}
}
}
The only needed modifications is in root view.
For your first screen you can add .navigationBarHidden(true) inside your NavigationView to hide it and false on second screen to unhide.
FIRST SCREEN:
NavigationView{
Button(action: {}, label: {
Text("Button")
})
.navigationBarHidden(true) //This flag will hide your navigationBar
}
SECOND SCREEN:
NavigationView{
Button(action: {}, label: {
Text("Button")
})
.navigationBarHidden(false) //This flag will unhide your navigationBar
}

Remove space NavigationTitle but not the back button

I want to remove the NavigationTitle Space without removing the back button.
I have already tried this:
.navigationBarItems(trailing:
NavigationLink(destination: Preferences(viewModel: viewModel).navigationBarHidden(true)) {
Image(systemName: "gear")
.font(.title2)
}
)
but that removes the back button as well.
Standard Back button cannot be shown without navigation bar, because it is navigation item, so part of navigation bar. I assume you just need transparent navigation bar.
Here is demo of possible solution (tested with Xcode 12.1 / iOS 14.1) / images are used for better visibility /
struct ContentView: View {
init() {
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.configureWithTransparentBackground()
UINavigationBar.appearance().standardAppearance = navBarAppearance
}
var body: some View {
NavigationView {
ZStack {
Image("large_image")
NavigationLink(destination: Image("large_image")) {
Text("Go to details ->")
}
}
.navigationBarItems(trailing: Button(action: {}) {
Image(systemName: "gear")
.font(.title2)
}
)
.navigationBarTitle("", displayMode: .inline)
}.accentColor(.red)
}
}

Resources