I am using a tab view to change screens in my app. I am also using a custom tab bar that I created to navigate with.
The problem I have is the tab view seems like it's creating a random blank space underneath itself. I can't figure out if it's the custom tab view or not.
IMPORTANT: One thing to note is that if you click anywhere in the blank space it will actually navigate through the views - so it seems like it is actually an invisible tab bar?
Below is a screenshot of the issue:
ContentView:
struct ContentView: View {
@State var selectedTab = 0
var body: some View {
VStack {
TabView(selection: $selectedTab) {
MyGarageView().tag(0)
FuelView().tag(1)
FinderView().tag(2)
}
}
ZStack{
HStack{
ForEach((TabbedItems.allCases), id: \.self){ item in
Button{
selectedTab = item.rawValue
} label: {
CustomTabItem(imageName: item.iconName, title: item.title, isActive: (selectedTab == item.rawValue))
}
}
}
.padding(6)
}
.frame(height: 75)
.cornerRadius(15)
.padding(.horizontal, 26)
}
}
CustomTabBarView:
enum TabbedItems: Int, CaseIterable{
case myGarage = 0
case fuel
case map
var title: String{
switch self {
case .myGarage:
return "Garage"
case .fuel:
return "Fuel"
case .map:
return "Finder"
}
}
var iconName: String {
switch self {
case .myGarage:
return "garage"
case .fuel:
return "fuel"
case .map:
return "map"
}
}
}
extension ContentView {
func CustomTabItem(imageName: String, title: String, isActive: Bool) -> some View {
HStack(spacing: 10){
Spacer()
Image(imageName)
.resizable()
.renderingMode(.template)
.foregroundColor(isActive ? .white : .gray)
.frame(width: 20, height: 20)
if isActive{
Text(title)
.font(.system(size: 14))
.foregroundColor(isActive ? .white : .black)
}
Spacer()
}
.frame(width: isActive ? 150 : 60, height: 60)
.background(isActive ? .black : .clear)
.cornerRadius(15)
}
}
I've tried hiding the tab view to no avail.
I've also tried playing around with the frames which had no effect.
I cannot see the issue and other posts / articles did not help either. I'm stuck :(
The normal way to use a TabView
is either to have a tab bar which is populated with TabItem
, or to use page view style.
TabItem
to each of the views in the TabView
.You are not using either of these approaches. So there is no real need to be using a TabView
.
However, if you really want to use a TabView
, then one workaround for the blank space (when .automatic
tab style is used) is to show the custom tab bar as an overlay. You might need to add more padding below the TabView
to make more space for your custom tab bar, if the height of your tab bar is greater than the blank space you are trying to hide.
Like this:
var body: some View {
TabView(selection: $selectedTab) {
MyGarageView().tag(0)
FuelView().tag(1)
FinderView().tag(2)
}
.padding(.bottom, 30)
.overlay(alignment: .bottom) {
HStack{
ForEach((TabbedItems.allCases), id: \.self){ item in
Button{
selectedTab = item.rawValue
} label: {
CustomTabItem(imageName: item.iconName, title: item.title, isActive: (selectedTab == item.rawValue))
}
}
}
.padding(6)
.frame(height: 75)
.cornerRadius(15)
.padding(.horizontal, 26)
}
}
Although this works, you are relying on the blank space below the TabView
being there, because if it wasn't there, your custom tab bar would overlap the page content. So you might want to reconsider, whether you really need to use a TabView
at all.
An alternative approach would be to replace the TabView
with a ZStack
and then to switch between the different views according to the setting of the state variable selectedTab
. The custom tab bar would work in exactly the same way. By avoiding TabView
altogether, you would not be vulnerable to the layout of a TabView
changing in a future iOS version.