I got a NavigationBar at the Bottom of some of my Views, but not all of them. It looks like this:
And I need it to refresh in every View once I change to another View since I want to implement changing the Button colors to represent which View is active at the moment. So if the current View is Home I want it to look like this:
This is the code for the buttonbar:
struct ButtonBar: View {
@State var selection: Int? = nil
var body: some View {
HStack {
NavigationLink(destination: ShopView(), tag: 1, selection: $selection) {
Button() {
self.selection = 1
} label: {
Image("shoppingCart").resizable()
.renderingMode(.template)
.foregroundColor(selection == 1 ? Color.blue : Color(.init(red: 0.59, green: 0.62, blue: 0.67, alpha: 1)))
.frame(width: 34, height: 34)
}
}
Spacer()
NavigationLink(destination: HomeView(), tag: 2, selection: $selection) {
Button() {
self.selection = 2
} label: {
Image("home").resizable()
.renderingMode(.template)
.foregroundColor(selection == 2 ? Color.blue : Color(.init(red: 0.59, green: 0.62, blue: 0.67, alpha: 1)))
.frame(width: 34, height: 34)
}
}
Spacer()
NavigationLink(destination: MessagesView(), tag: 3, selection: $selection) {
Button() {
self.selection = 3
} label: {
Image("message").resizable()
.renderingMode(.template)
.foregroundColor(Color(.init(red: 0.59, green: 0.62, blue: 0.67, alpha: 1)))
.frame(width: 24, height: 24)
}
}
Spacer()
NavigationLink(destination: EventsView(), tag: 4, selection: $selection) {
Button() {
self.selection = 4
} label: {
Image("calender").resizable()
.renderingMode(.template)
.foregroundColor(Color(.init(red: 0.59, green: 0.62, blue: 0.67, alpha: 1)))
.frame(width: 34, height: 34)
}
}
Spacer()
NavigationLink(destination: SettingsView(), tag: 5, selection: $selection) {
Button() {
self.selection = 5
} label: {
Image("personCover").resizable()
.renderingMode(.template)
.foregroundColor(Color(.init(red: 0.59, green: 0.62, blue: 0.67, alpha: 1)))
.frame(width: 36, height: 36)
}
}
}.padding(.init(top: 0, leading: 8, bottom: 8, trailing: 8))
}
}
When I render this View in my Views like this ButtonBar()
it does not refresh colors since it is created as a new View in every View. Is there a way to pass a View as an environmentObject just like with States?
CodePudding user response:
Using TabView
would work perfectly if I didn't need custom buttons, but this code worked for me:
import Foundation
class ViewRouter: ObservableObject {
@Published var currentPage: Page = .home
}
enum Page {
case home
case shop
case messages
case events
case settings
}
struct ContentView: View {
@StateObject var viewRouter = ViewRouter()
var body: some View {
VStack {
ZStack {
switch viewRouter.currentPage {
case .shop:
ShopView().environmentObject(loginViewController)
case .home:
HomeView()
case .messages:
MessagesView()
case .events:
EventsView()
case .settings:
SettingsView()
}
}
HStack {
Button() {
viewRouter.currentPage = .shop
} label: {
Image("shoppingCart").resizable()
.renderingMode(.template)
.foregroundColor(viewRouter.currentPage == .shop ? Color.blue : Color(.init(red: 0.59, green: 0.62, blue: 0.67, alpha: 1)))
.frame(width: 34, height: 34)
}
Spacer()
Button() {
viewRouter.currentPage = .home
} label: {
Image("home").resizable()
.renderingMode(.template)
.foregroundColor(viewRouter.currentPage == .home ? Color.blue : Color(.init(red: 0.59, green: 0.62, blue: 0.67, alpha: 1)))
.frame(width: 34, height: 34)
}
Spacer()
Button() {
viewRouter.currentPage = .messages
} label: {
Image("message").resizable()
.renderingMode(.template)
.foregroundColor(viewRouter.currentPage == .messages ? Color.blue : Color(.init(red: 0.59, green: 0.62, blue: 0.67, alpha: 1)))
.frame(width: 24, height: 24)
}
Spacer()
Button() {
viewRouter.currentPage = .events
} label: {
Image("calender").resizable()
.renderingMode(.template)
.foregroundColor(viewRouter.currentPage == .events ? Color.blue : Color(.init(red: 0.59, green: 0.62, blue: 0.67, alpha: 1)))
.frame(width: 34, height: 34)
}
Spacer()
Button() {
viewRouter.currentPage = .settings
} label: {
Image("personCover").resizable()
.renderingMode(.template)
.foregroundColor(viewRouter.currentPage == .settings ? Color.blue : Color(.init(red: 0.59, green: 0.62, blue: 0.67, alpha: 1)))
.frame(width: 36, height: 36)
}
}.padding(.init(top: 0, leading: 8, bottom: 8, trailing: 8))
}
}
}
}
CodePudding user response:
Create your TabView in ContentView. There'll be three tab items: one that will lead the user to HomeView, one that will lead the user to ShopView, and another one to MessageView.Make sure to have a Navigation Link in your parent View that will lead to a child View. For example, in the code below:
import SwiftUI
struct ContentView: View {
@State private var selection = 0
var body: some View {
NavigationView {
TabView(selection: $selection){
NavigationLink(destination: HomeView()){
Text("Home Tab")
.font(.system(size: 30, weight: .bold, design: .rounded))
}
.tabItem {
Image(systemName: "house.fill")
Text("Home")
}
.tag(0)
NavigationLink(destination: ShopView()){
Text("Shop Tab")
.font(.system(size: 30, weight: .bold, design: .rounded))
}
.tabItem {
Image(systemName: "bookmark.circle.fill")
Text("Shop")
}
.tag(1)
NavigationLink(destination: MessageView()){
Text("Message Tab")
.font(.system(size: 30, weight: .bold, design: .rounded))
}
.tabItem {
Image(systemName: "message.fill")
Text("Message")
}
.tag(2)
}
.accentColor(.yellow)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}