Creating a navbar with 3 items - swift

I'm trying to create something like this:
A navigation bar with 3 items, is it possible to do this using navigationBarItems?
My current plan is to hide the navbar using:
.navigationBarTitle("")
.navigationBarHidden(true)
and then creating the 3 buttons using a HStack. The Problem I have is because I'm hiding the navbar, the click of one of the buttons take it to another view, which also then hides the navbar (Thats not what im looking for)
I have tried:
.navigationBarItems(trailing:
HStack {
Button("About") {
print("About tapped!")
}
Button("Help") {
print("Help tapped!")
}
}
)
But this creates the two items next to each other on the right side. I tried putting a Spacer() in the above HStack, but this doesn't work.
I would prefer to use navigationBarItems but can't seem to find a way to centre an item?

A navigation bar with 3 items, is it possible to do this using navigationBarItems?
No. Moreover navigationBarItems modifier is deprecated since SwiftUI 2.0
SwiftUI 2.0
This can be done with toolbar modifier as easy as attach it to any view inside NavigationView
Demo prepared & tested with Xcode 12 / iOS 14:
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button(action: {}) { Image(systemName: "gear") }
}
ToolbarItem(placement: .principal) {
Button(action: {}) { Image(systemName: "car") }
}
ToolbarItem(placement: .navigation) {
Button(action: {}) { Image(systemName: "chevron.left") }
}

Related

How to make a ToolbarItem centered while keeping others trailing and leading in SwiftUI for macOS?

Build for macOS. I want to make a toolbar like Safari's toolbar, that there are three parts (leading, centered, and trailing). And the centered part stays at the absolutely center, no matter how long leading or trailing part is or changes to.
My code would be like below, but failed to achieve my requirement. As shown in the screenshot below, the trailing placements (.confirmationAction, .primaryAction, .automatic etc.) all don't work. If a ToolbarItem whose placement is .principal exists, the trailing part attach to it closely. Also, I find the .principal is not absolutely centered. The position is depending on the leading part.
How can I solve this and meet the requirement? Or some alternative methods rather than .toolbar{}?
.toolbar {
ToolbarItem(placement: .principal) {
Button {} label: {
Image(systemName: "star.fill")
.scaleEffect(1.5)
}
}
ToolbarItem(placement: .confirmationAction) {
Button {} label: {
Image(systemName: "star")
}
}
}
Using Spacer() is the best option here because it will separate space between your item fairly. Put your images/components between Spacer().You can use this method with other Stack/Container too, not just HStack. NOTE: this is an alternative way relates to poster's request. Try code below the image:
import SwiftUI
struct UsingSpacer__: View {
var body: some View {
VStack {
Spacer()
HStack {
Spacer()
Image(systemName: "square.fill")
Spacer()
Image(systemName: "circle.fill")
Spacer()
Image(systemName: "cloud.fill")
Spacer()
}
.background(.blue)
}
}
}

How come my NavigationLink won't work when clicked?

I am trying to make it so that when I click the icon, the "scoreView()" is opened. When I click it, nothing works right now. Here is the code:
HStack {
Image(systemName: "arrow.counterclockwise")
NavigationLink(destination: scoreView(scoreTracker: $scoreTracker)) {
Spacer()
Image(systemName: "list.bullet")
}
}
Does it have something to do with the fact that I don't have a navigationView? I'm new to this and experimenting so I'm not very clear on it.
EDIT:
I have added a NavigationView, yet the NavigationLink covers half the screen, and when clicked, the view is only changed in that square.
Before clicking the NavigationLink
After clicking the NavigationLink
HStack {
Image(systemName: "arrow.counterclockwise")
NavigationView {
NavigationLink(destination: scoreView(scoreTracker: $scoreTracker)) {
Image(systemName: "list.bullet")
}
}
}
Does it have something to do with the fact that I don't have a navigationView?
Yes. According to the documentation:
Users click or tap a navigation link to present a view inside a NavigationView.
It will only work inside a NavigationView. If you're not using one, consider sheet or fullScreenCover instead. Or, make your own overlay with a ZStack.
Example NavigationView usage:
struct ContentView: View {
var body: some View {
NavigationView { /// directly inside `var body: some View`
VStack { /// if you have multiple views, make sure to put them in a `VStack` or similar
Text("Some text")
/// `ScoreView` should be capitalized
NavigationLink(destination: ScoreView(scoreTracker: $scoreTracker)) {
Image(systemName: "list.bullet")
}
}
}
}
}

Button grayed out in toolbar initially

I have a SwiftUI macOS application, and I noticed that when you have a button in a toolbar, its image is initially grayed out until you hover over or click it.
I am using macOS Montery Beta 3, and Xcode 13 Beta 3.
Simple Reproduction
Create a new SwiftUI macOS project
Paste the following code:
struct ContentView: View {
var body: some View {
NavigationView {
Text("Panel1").padding()
.toolbar {
Button(action: {}) {
Image(systemName: "plus")
}
}
Text("Panel2").padding()
}
}
}
Run the application, and you should see that the plus button is grayed out. However hovering over or clicking it makes the button not gray.
This question is very similar to this, but instead with a toolbar.
Whats happening here?
I had the same issue and discovered that you need to specify the color explicitly.
.toolbar {
Button(action: {}) {
Image(systemName: "plus")
}
Button(action: {}) {
Image(systemName: "plus")
.foregroundColor(.white)
}
}

macOS toolbar items with image and text in SwiftUI

I'd like to achieve something similar in SwiftUI to what is described in Apple's Human Interface Guidelines about toolbars.
I tried using .toolbar { } but items are too small and NavigationLink doesn't change the selected View. I tried setting ExpandedWindowToolbarStyle() on WindowGroup.
Code:
NavigationView { }
.toolbar {
ToolbarItem(placement: ToolbarItemPlacement.automatic) {
HStack {
Text("")
NavigationLink(
destination: getDestination(forOption: Option.home)) {
VStack {
Image(systemName: Option.home.iconName)
Text("test")
}
.frame(height: 50)
}
}
}
}
current state:
You can use a customizable toolbar and labels.
.toolbar(id: "Main") {
ToolbarItem(id: "Sidebar") {
Button(action: {}) {
Label("Sidebar", systemImage: "sidebar.right")
}
}
}
Also it might be possible to use TitleAndIconLabelStyle with MacOS 11.3. I haven't tried it yet.

NavigationLink buttons on tvOS with SwiftUI not working

I am trying to build a simple navigation UI on Apple TV with SwiftUI:
As I can tell, I need to use either NavigationLink or NavigationLink combined with Button.
I have tried several implementations and none of them worked:
NavigationLink(destination: view2) {
Image("placeholder").frame(width:400, height: 300)
Text("Button")
}
NavigationLink(destination: view2) {
Button(action: {print("hey")}) {
VStack{
Image("placeholder").frame(width:400, height: 300)
Text("Button")
}
}
}
Button(action: {print("hi1")}) {
VStack{
Image("placeholder").frame(width:400, height: 300)
Text("Button")
}
}.background(NavigationLink(destination: view2) { Text("hi2") })
NavigationLink(destination: view2) {
Text("hey")
}.background(Button(action: {print("hey")}) {
VStack{
Image("placeholder").frame(width:400, height: 300)
Text("Button")
}
})
The first two ones are not selectable with Magic Remote: they won't become focused. The last ones are simply not navigating to another view when I press on them.
How do I implement this style of navigation on tvOS with SwiftUI?
NavigationLink works by itself, standalone, only on watchOS (that might confuse), in all other supported OSs it should be included in NavigationView to operate, so
in pseudo-code
NavigationView {
// ... some code
NavigationLink(...) // must be anywhere inside
// ... other code
}