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.
Related
I would like to change the color of navigationTitle inside NavigationStack.
struct InterestView: View {
var body: some View {
NavigationStack {
VStack {
}
.navigationTitle("interest".uppercased())
.toolbar {
ToolbarItemGroup(placement: .navigationBarTrailing) {
Button {
print("Image tapped!")
} label: {
Text("add".uppercased())
.foregroundColor(Color.primaryColor)
.font(.headline)
}
}
}
}
}
}
I could not find any modifier to change it.
In SwiftUI, you cannot change title color with a simple modifier. You need to change UINavigation Appearance but this will effect globally.
Alternative solution:
You are already using toolbar, so adding title to toolbar is easy as follow. I hope this solves your problem.
struct InterestView: View {
var body: some View {
NavigationStack {
VStack {
}
.toolbar {
ToolbarItemGroup(placement: .principal) {
Text("interest".uppercased())
.foregroundColor(.red)
}
ToolbarItemGroup(placement: .navigationBarTrailing) {
Button {
print("Image tapped!")
} label: {
Text("add".uppercased())
.foregroundColor(Color.red)
.font(.headline)
}
}
}
}
}
}
I have a very simple NavigationStack that I would like to customise the title, but I can't seem to find the right modifiers to achieve this.
NavigationStack {
List {
NavigationLink {
Text("My Child View")
} label: {
Label("Child View")
}
}.navigationTitle("Parent View")
}
I would like to change how the font looks for the .navigationTitle and be able to add a button to the right. When I add a .font modifier to .navigationTitle it adds it to the list items, not the title. And .navigationTitle only appears to accept a string.
I am looking to achieve the below (my button will be a + rather than a chevron).
From what I can tell, I can't use navigationTitle to achieve this. However, if I don't use that, then the back button has the wrong title (it uses the text Back instead of Parent View).
You can achieve both using the .toolbar modifier:
public var body: some View {
NavigationStack {
List {
NavigationLink {
Text("My Child View")
} label: {
Label("Child View", systemImage: "questionmark")
}
}
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Text("Parent View")
.font(.system(size: 22, weight: .bold))
}
ToolbarItem(placement: .navigationBarTrailing) {
Button {
} label: {
Image(systemName: "plus")
}
}
}
}
}
I have a problem. I have empty space on the top of my views, and I think that the problem is the Navigation View. View Image
I figured it out to make it work and hide that empty space with this line of code, but if I'm using this approach, my toolbar items dissapears too, and I do not want this.
.navigationBarHidden(true)
I'll share my code below. Thanks !
TabView{
NavigationView{
VStack {
MeniuriView()
NavigationLink(isActive: $optionsActive) {
WaitingOrderView()
.environmentObject(syncViewModel)
} label: {
EmptyView()
}
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
ToolbarButtons(numberOfProducts: menus.count) {
optionsActive = true
}
}
ToolbarItem(placement: .navigationBarLeading) {
Text(Texts.mainViewText1)
.font(.system(size: 24))
.fontWeight(.bold)
.padding()
}
}
}
.tabItem {
Text(Texts.mainViewText2)
Image(systemName: "fork.knife")
}
}
struct MeniuriView: View {
#EnvironmentObject var syncViewModel : SyncViewModel
var body: some View {
List {
ForEach(syncViewModel.menuType) { type in
SectionView(menuType: type)
}
}
.listStyle(PlainListStyle())
}
}
The space is reserved for the (large) NavigationTitle. You can use
.navigationBarTitleDisplayMode(.inline)
on the NavigationView to make it small. And if its empty, it won't show.
In Apple's calendar app, they provide a toolbar item that toggles its style based on some state. It essentially acts as a Toggle. I'm trying to re-create this same thing in SwiftUI and make it work well in both light and dark mode. I was able to make a view that works as intended, until I put it into the toolbar and it no longer shows the selected state. Here is my attempt:
struct ToggleButtonView: View {
#State private var isOn = false
var body: some View {
Button(action: {
isOn.toggle()
}, label: {
if isOn {
Image(systemName: "list.bullet.below.rectangle")
.accentColor(Color(.systemBackground))
.background(RoundedRectangle(cornerRadius: 5.0)
.fill(Color.accentColor)
.frame(width: 26, height: 26))
} else {
Image(systemName: "list.bullet.below.rectangle")
}
})
.accentColor(.red)
}
}
And here is how I am actually placing the button into the toolbar:
struct TestView: View {
var body: some View {
NavigationView {
ScrollView {
ForEach(0..<5) { number in
Text("Number \(number)")
}
}
.toolbar {
ToolbarItemGroup(placement: .navigationBarTrailing) {
ToggleButtonView()
Button(action: {}, label: {
Image(systemName: "plus")
})
}
}
.navigationTitle("Plz halp")
}
.accentColor(.red)
}
}
Here are screenshots from the calendar app. Notice the toolbar item to the left of the search icon.
you could try this:
.toolbar {
// placement as you see fit
ToolbarItem(placement: .navigationBarTrailing) {
ToggleButtonView()
}
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {}, label: {
Image(systemName: "plus")
})
}
}
This looks like an issue with how SwiftUI handles ToolbarItems before iOS 15. According to Asperi's answer to a similar question, "...all standards types (button, image, text, etc) are intercepted by ToolbarItem and converted into an appropriate internal representation."
Toggle buttons in SwiftUI iOS 15
Interestingly enough, iOS 15 now provides a standard solution to the use-case above using the .button toggle style, as shown in the following code:
struct ContentView: View {
#State private var isOn = false
var body: some View {
Toggle(isOn: $isOn) {
Image(systemName: "list.bullet.below.rectangle")
}
}
}
I don't know how to create an UIToolbar at the bottom of the screen in SwiftUI.
There is no controller in SwiftUI but you can add like this.
var body: some View {
NavigationView {
VStack {
List(model.items) { item in
ItemViewRow(item: item)
}
HStack {
Button(action: {
}) {
Image(systemName: "someimage")
}
Spacer()
Button(action: {
}) {
Image(systemName: "someimage")
}
}.padding()
}
.navigationBarTitle(Text("Items"))
}
}