Change Tabbar Icon Image SwiftUI - swiftui

I want to change tabItem icon image when tapped on one of the tabItem in this code. How can it be done?
var body: some View {
ZStack {
TabView(selection:$selection) {
OffersView()
.tabItem ({
Image(systemName: "bag").renderingMode(.template)
Text("Offers")
})
.tag(1)
StepView()
.tabItem ({
Image(systemName: "figure.walk.circle").renderingMode(.template)
Text("Steps")
})
.tag(2)
ProfileView()
.tabItem {
Image(systemName: "person")
Text("Profile")
}
.tag(3)
}
.accentColor(Color("ColorOnboarding"))
.navigationBarBackButtonHidden(true)
}

You can change image like this,
var body: some View {
ZStack {
TabView(selection:$selection) {
OffersView()
.tabItem ({
Image(systemName: selection == 1 ? "bag" : "bag2").renderingMode(.template)
Text("Offers")
})
.tag(1)
StepView()
.tabItem ({
Image(systemName: selection == 2 ? "figure.walk.circle" : "figure.walk.circle2").renderingMode(.template)
Text("Steps")
})
.tag(2)
// -----Other Code-----

You can use state for it
var body: some View {
#State var isTapped = false
ZStack {
TabView(selection:$isTapped) {
OffersView()
.tabItem ({
Image(systemName: selection == 1 ? "bag" : "bag2").renderingMode(.template)
Text("Offers")
})
.tag(1)
StepView()
.tabItem ({
Image(systemName: selection == 2 ? "figure.walk.circle" : "figure.walk.circle2").renderingMode(.template)
Text("Steps")
})
.tag(2)
ProfileView()
.tabItem {
Image(systemName: "person")
Text("Profile")
}
.tag(3)
}
.accentColor(Color("ColorOnboarding"))
.navigationBarBackButtonHidden(true)
}

Related

How to hide the Back Button (More) of a View inside TabView

I have a TabView with many items and I would like to hide the back button (<More) from the last one.
struct ExperimentView: View {
var body: some View {
TabView {
AView(label: "1")
.tabItem {
Label("Tab1", systemImage: "list.dash")
}
AView(label: "2")
.tabItem {
Label("Tab2", systemImage: "square.and.pencil")
}
AView(label: "3")
.tabItem {
Label("Tab3", systemImage: "pencil.slash")
}
AView(label: "4")
.tabItem {
Label("Tab4", systemImage: "scribble")
}
AView(label: "5")
.tabItem {
Label("Tab5", systemImage: "pencil.tip")
}
AView(label: "6")
.tabItem {
Label("Tab6", systemImage: "pencil.and.outline")
}
}
}
}
struct AView: View {
var label: String
var body: some View {
VStack {
Spacer()
Text(label)
Spacer()
}
}
}
I tried:
AView(label: "6")
.navigationBarTitle("")
.navigationBarBackButtonHidden(true)
.tabItem {
Label("Tab6", systemImage: "pencil.and.outline")
}
but it did't help.

SwiftUI: How to update image to filled / outlined in TabView

I'm trying to use filled image when it is selected and outlined image when it is deselected. I tried to render the images but still filled
So I thought this would work, but it doesn't:
struct ListTabView: View {
#State private var selectedTab = 0
var body: some View {
NavigationView {
TabView(selection: $selectedTab) {
Text("Tab 1")
.onTapGesture {
self.selectedTab += 1
}
.tabItem {
selectedTab == 0 ? Image(systemName: "star.fill") : Image(systemName: "star")
Text("First")
}
.tag(0)
Text("Tab 2")
.onTapGesture {
self.selectedTab -= 1
}
.tabItem {
selectedTab == 1 ? Image(systemName: "moon.stars.fill") : Image(systemName: "moon.stars")
Text("Second")
}
.tag(1)
}
.accentColor(.pink)
.onAppear {
UITabBar.appearance().barTintColor = .white
}
}
}
}
struct ListTabView_Previews: PreviewProvider {
static var previews: some View {
ListTabView()
}
}
Your code actually works. The issue is something else not documented that I can find. If you use a non .fill variant of an SF Font, the .fill variant will be substituted. Use the following code to test it:
TabView(selection: $selectedTab) {
VStack {
Text("Tab 1")
Text(Image(systemName: "star"))
}
.tabItem {
selectedTab == 0 ? Image(systemName: "star") : Image(systemName: "sun.max")
Text("First")
}
.tag(0)
VStack {
Text("Tab 2")
Text(Image(systemName: "moon.stars"))
}
.tabItem {
selectedTab == 1 ? Image(systemName: "moon.stars") : Image(systemName: "sun.max")
Text("Second")
}
.tag(1)
}
You will note I used plain variants, and yet the filled variant was used. Also, you don't need the .onTap(), but I suspect you added it when the images didn't seem to switch.
You can add this to Image / Label:
Image(systemName: selectedTab == 0 ? "star.fill" : "star")
.environment(\.symbolVariants, selectedTabItemIndex == 0 ? .fill : .none)
It will allow you to set the symbol variants as you would expect it.

Show selected tab in TabView in SwiftUI

When using TabView in SwiftUI, what can I do to show the selected Tab like in the following picture?
I've tried creating a VStack within each tab like this:
struct ContentView: View {
#State public var tabViewSelection = 0
var body: some View {
TabView(selection: $tabViewSelection) {
HomeFirstLevel()
.tabItem {
VStack {
Image("HomeIcon")
Rectangle()
.frame(height: 7)
.foregroundColor((tabViewSelection == 0) ? .black : .clear)
}
}.tag(0)
}
}
}
But it's not working.
I can't even seem to add a Rectangle instead of an Image:
HomeFirstLevel()
.tabItem {
Rectangle()
}.tag(0)
Does TabView not accept shapes?
Thanks in advance for the help!
You can not set shape in tabItem. But you can use ZStack to add shape over the tab bar and set the x position.
Here is the demo.
struct ContentViewTabDemo: View {
#State public var tabViewSelection = 0
private var singleTabWidth = UIScreen.main.bounds.width / 5
var body: some View {
ZStack(alignment: .bottomLeading) {
TabView(selection: $tabViewSelection) {
Color.red
.tabItem {
VStack {
Image(systemName: "circle.fill")
}
}.tag(0)
Color.blue
.tabItem {
VStack {
Image(systemName: "heart.fill")
}
}.tag(1)
Color.red
.tabItem {
VStack {
Image(systemName: "circle.fill")
}
}.tag(2)
Color.blue
.tabItem {
VStack {
Image(systemName: "heart.fill")
}
}.tag(3)
Color.red
.tabItem {
VStack {
Image(systemName: "circle.fill")
}
}.tag(4)
}
Rectangle()
.offset(x: singleTabWidth * CGFloat(tabViewSelection))
.frame(width: singleTabWidth, height: 7)
.padding(.bottom, 2)
.animation(.default)
}
}
}

TabBar Change Selected Tab Icon Background Color swiftui

I have this TabBArViewController which has 5 tabs in it.
struct TabBarViewController: View {
#State private var selection = 3
var body: some View {
ZStack {
TabView(selection:$selection) {
OffersView()
.tabItem ({
Image(systemName: "bag").renderingMode(.template)
Text("Offers")
})
.tag(1)
BalanceView()
.tabItem ({
Image(systemName: "creditcard").renderingMode(.template)
Text("Balance")
})
.tag(2)
StepView()
.tabItem ({
Image(systemName: "figure.walk.circle").renderingMode(.template)
Text("Steps")
})
.tag(3)
FriendsView()
.tabItem {
Image(systemName: "person.2")
Text("Friends")
}
.tag(4)
ProfileView()
.tabItem {
Image(systemName: "person")
Text("Profile")
}
.tag(5)
}
.accentColor(Color("ColorOnboarding"))
.navigationBarBackButtonHidden(true)
}
.navigationBarBackButtonHidden(true)
}
}
which appears as so
I want to add a rectangle color to this when a tab bar icon selected in SwiftUI. How can I do it without creating a custom tab bar?

How to perform a modal transition like the center button in the Instagram app with SwiftUI TabView?

import SwiftUI
struct ContentView: View {
#State var showModal = false
var body: some View {
TabView {
Text("Home View")
.tabItem {
VStack {
Image(systemName: "house")
Text("Home")
}
}
Text("Dummy View")
.onAppear {
self.showModal = true
}
.sheet(isPresented: self.$showModal) {
Text("Camera View")
}
.tabItem {
VStack {
Image(systemName: "camera")
Text("Camera")
}
}
Text("Setting View")
.tabItem {
VStack {
Image(systemName: "person")
Text("Setting")
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
When I tap the center camera button with above code,
"Dummy View" has been shown.
onAppear is called and self.showModal is set to true.
But, modal transition is not performed, and can not show the "Camera View".
How to perform a modal transition when tapped tab button with SwiftUI TabView?
Thank you krjw!
Finally, I have solved the problem with the following code:
import SwiftUI
struct ContentView: View {
#State var showModal = false
var body: some View {
TabView {
Text("Home View")
.tabItem {
VStack {
Image(systemName: "house")
Text("Home")
}
}
Text("Dummy View")
.onAppear {
DispatchQueue.main.async {
self.showModal = true
}
}
.sheet(isPresented: self.$showModal) {
Text("Camera View")
}
.tabItem {
VStack {
Image(systemName: "camera")
Text("Camera")
}
}
Text("Setting View")
.tabItem {
VStack {
Image(systemName: "person")
Text("Setting")
}
}
}
}
}
I had trouble with that and I am not sure why, but .sheet always worked best for me when I put it on the very top of my view hierarchy. Additionally I wrapped the call in .onAppear to run explicitly on the main queue (UI) which got it working:
struct ContentView: View {
#State var showModal = false
var body: some View {
TabView {
Text("Home View")
.tabItem {
VStack {
Image(systemName: "house")
Text("Home")
}
}
Text("Dummy View")
.onAppear {
print("Hallo")
DispatchQueue.main.async {
self.showModal = true
}
}
.tabItem {
VStack {
Image(systemName: "camera")
Text("Camera")
}
}
Text("Setting View")
.tabItem {
VStack {
Image(systemName: "person")
Text("Setting")
}
}
}
.sheet(isPresented: self.$showModal) {
Text("Camera View")
}
}
}
I hope this helps!