SwiftUI - How to add button as a navigation title? - ios

Is it possible to make the navbar title clickable like a button?
Tried .navigationBarTitle(Button(....)), but this won’t work bc button doesn't conform to string protocol...

Here is a possible solution
struct ContentView: View {
var body: some View {
NavigationView {
GeometryReader { geo in
List {
Text("Have a nice day!")
Text("Today is sunny")
}.navigationBarTitle(Text(""), displayMode: .inline)
.navigationBarItems(leading: HStack{
Spacer().frame(width: geo.size.width * 0.5)
VStack{
Text("Title")
Button(action: {
print("I'm feeling lucky ;)")
})
{
Text("Button")
}
}
Spacer().frame(width: geo.size.width * 0.5)
})
}
}
}
}

You can not create a button on NavigationTitle in SwiftUI Navigation View
Solution: You have to create custom Navigation Bar & Other Views

Related

Combine NavigationTitle and Navigation Back Button SwiftUI

I have an app that has a navigationLink from one view to another, but when the NavLink moves to the second view, the NavigationTitle of that view is pushed, down, it's not inline. Is there any way to combine the toolbar and the title? I put my code below.
import SwiftUI
struct FirstView: View {
var body: some View {
NavigationView {
Text("My Stuff")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing){
NavigationLink(destination: SettingsView(), label: {
Image(systemName: "gear")
.font(.system(size: 25))
.navigationTitle("My Stuff")
})
}
}
}
}
}
And the second view:
import SwiftUI
struct SettingsView: View {
var body: some View {
NavigationView {
VStack {
Text("Settings View")
.navigationTitle("Settings")
}
}
}
}
A photo below of what is happening:
Thank you for your help.
jnpdx solved this... the solution was that I had an extra NavigationView in my SettingsView. I only needed one NavigationView.

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 set the color of a NavigationView symbol button

My currently have a NavigationView with an embedded ToolbarItemGroup containing buttons with SF Symbols. I'm attempting to change the Trash button's color to that of red.
var body: some View {
NavigationView {
Text("Hello, World!")
.navigationTitle("Today")
.toolbar {
ToolbarItemGroup(placement: .navigationBarTrailing) {
Button(action: {
print("Add button was tapped")
}) {
HStack {
Image(.add)
}
}
Button(action: {
print("Trash button was tapped")
}) {
HStack {
Image(.trash)
.foregroundColor(.red)
.accentColor(.red)
}
}
.foregroundColor(.red)
.accentColor(.red)
}
}
}
}
I can't seem to set the color of the Trash image symbol to red. Image(.trash) is no typo, I'm using this extension I wrote!
Thanks :)
You can add .accentColor(.red) to the NavigationView. Although it will change the color of all ToolBar Items. An example would be
NavigationView {
SomeViews
}
.accentColor(.red)
It did the trick, as shown here
An other way to work on NavigationView. Although it will change the color of all ToolBar Items, too.
struct ContentView: View {
init() {
UINavigationBar.appearance().tintColor = UIColor.magenta
}
// your code follows
}

SwiftUI Bring Down Navigation Items

In my SwiftUI app, I would like to bring the navigation bar items down like in Apple's own UIKit apps.
Seen below is a screenshot from the Health app. Notice how the profile picture is in line with the 'Summary' text. This is what I am looking to achieve.
I have tried using .padding(.top, 90) but this has not worked as it does not bring down the virtual box that allows the button to be clicked. Using padding means that you have to tap the button above the image/text.
Thank you.
Unfortunately I didn't find any solution for changing navigation bar height in iOS 13 with SwiftUI, and had the same issues earlier. Solution below will fit you, if your navigation bar is always only black and you're ok with gap on the top:
struct NavBarCustomItems: View {
init() {
setNavigationBarToBlackOnly()
}
func setNavigationBarToBlackOnly() {
let blackAppearance = UINavigationBarAppearance()
blackAppearance.configureWithOpaqueBackground()
blackAppearance.backgroundColor = .black
blackAppearance.shadowColor = .clear // to avoid border line
UINavigationBar.appearance().standardAppearance = blackAppearance
UINavigationBar.appearance().scrollEdgeAppearance = blackAppearance
}
var body: some View {
NavigationView {
VStack {
NavigationBarMimicry()
// here is your content
HStack {
Text("Favorites")
Spacer()
Button(action: {}) { Text("Edit") }
}
.padding()
Spacer()
VStack {
Text("Main screen")
}
// you need spacer(s) to be sure, that NavigationBarMimicry is always on the top
Spacer()
}
}
}
}
// MARK: here is what you need in navigation bar
struct NavigationBarMimicry: View {
var body: some View {
HStack {
Text("Summary")
.bold()
.font(.system(size: 40))
.foregroundColor(.white)
.padding(.horizontal)
Spacer()
Rectangle()
.foregroundColor(.white)
.frame(width: 40)
.padding(.horizontal)
}
.background(Color.black)
.frame(height: 40)
.navigationBarTitle("", displayMode: .inline)
// you can add it to hide navigation bar, navigation will work via NavigationLink
// .navigationBarHidden(true)
}
}
struct NavBarCustomItems_Previews: PreviewProvider {
static var previews: some View {
NavBarCustomItems().environment(\.colorScheme, .dark)
}
}
the result should be like this:
P.S. maybe the other ways are:
Put views in this order: VStack { NavigationBarMimicry(); NavigationView {...}};
uncomment line of code: .navigationBarHidden(true);

How to hide the TabBar when navigate with NavigationLink in SwiftUI?

I have a TabView with 2 tabs in it, each tab containing a NavigationView. I need to hide the TabBar when navigating to another view. One solution would be to place the TabView inside of one NavigationView, but I have to set different properties for each NavigationView.
TabView(selection: $selectedTab, content: {
NavigationView {
VStack {
NavigationLink(destination: Text("SecondView Tab1")) {
Text("Click")
}
}
}.tabItem {
Text("ONE")
}.tag(0)
NavigationView {
VStack {
NavigationLink(destination: Text("SecondView Tab2")) {
Text("Click")
}
}
}.tabItem {
Text("TWO")
}.tag(1)
})
P.S. I am using Xcode 11 Beta 5
A little late but it will work, put your NavigationView before the TabView and the tab buttons are going to be hidden when you use a navigation link in your tabbed views.
NavigationView{
TabView{
...
}
}
I have same problem for this;
And I did the following actions to solve this problem:
Use NavigationView Contain a TabView And Hidden the NavigationBar
Make a Custom NavigaitonView like this
In next view Still hidden NavigationBar
// root tab
NavigationView {
TabView {
// some
}
.navigationBarTitle(xxx, displayMode: .inline)
.navigationBarHidden(true)
}
// custom navigation view
#available(iOS 13.0.0, *)
struct MyNavigationView: View {
var body: some View {
HStack {
Spacer()
Text(some)
Spacer()
}
.frame(height: 44)
}
}
// this view
VStack {
MyNavigationView()
Image(some)
.resizable()
.frame(width: 100, height: 100, alignment: .top)
.padding(.top, 30)
Spacer()
HStack {
ClockView()
Spacer()
NavigationLink(
destination: DynamicList(),
label: {
Image(some)
}).navigationBarHidden(true)
}
.padding(EdgeInsets(top: 0, leading: 15, bottom: 0, trailing: 15))
Spacer()
}
// next view
var body: some View {
VStack {
List {
MyNavigationView()
ForEach(date, id: \.self) { model in
Text(model)
}
}
.navigationBarHidden(true)
.navigationBarTitle(some, displayMode: .inline)
}
}
You can't hide the tab bar as far as I know if you navigation view its listed as a child, your tab bar contains your navigation view.

Resources