my views all have a background (LinearGradien) but my CustomTabBar is white and then it all looks very cut off, to get around this I wanted to set the background to .clear but it stayed white. So my question is how to make it so that my tabBar is still there but takes on the background of the views.
Many thanks in advance
ContentView
struct ContentView: View {
@State private var selectedTab: Tab = .house
@State private var isProjectScreen: Bool = SharedDataIsProjectScreen.sharedVariable
init() {
UITabBar.appearance().isHidden = true
}
@State var isFullView:Bool = false
@State private var showSignInView: Bool = false
var body: some View {
VStack{
if !showSignInView {
VStack {
VStack {
TabView(selection: $selectedTab) {
dashboard_iphone_view(profilViewModel: ProfilViewModel(), design_selection: Design_selection())
.tag(Tab.house)
todo_iphone_view(profilViewModel: ProfilViewModel(), design_selection: Design_selection())
.tag(Tab.list)
pomodoro_timer_iphone(isFullView: $isFullView, profilViewModel: ProfilViewModel(), design_selection: Design_selection())
.tag(Tab.clock)
Listen_View(profilViewModel: ProfilViewModel(), design_selection: Design_selection())
.tag(Tab.listen)
}
}
if isFullView == false{
CustomTabBar(selectedTab: $selectedTab)
}
}
}
}
.statusBarHidden(isFullView)
}
}
CustomTabBar
import SwiftUI
enum Tab: String, CaseIterable {
case house = "house"
case list = "list.bullet.clipboard"
case clock = "clock"
//case folder = "folder"
case listen = "list.clipboard"
}
struct CustomTabBar: View {
@State var progress: Double = 0.50
@Binding var selectedTab: Tab
private var fillImage: String {
selectedTab.rawValue + ".fill"
}
private var tabColor: Color{
switch selectedTab {
case .house:
return .white
case .list:
return .white
case .clock:
return .white
//case .folder:
// return .marineblau
case .listen:
return .white
}
}
var body: some View {
VStack{
HStack{
ForEach(Tab.allCases, id: \.rawValue){ tab in
Spacer()
Image(systemName: selectedTab == tab ? fillImage : tab.rawValue)
.scaleEffect(selectedTab == tab ? 1.25 : 1.0)
.foregroundStyle(selectedTab == tab ? tabColor : Color(hex: "E8E8E8"))
.font(.system(size: 22))
.onTapGesture{
withAnimation(.easeIn(duration: 0.1)){
selectedTab = tab
}
}
Spacer()
}
}
}
.frame(width: nil, height: 60)
.background(.clear)
}
}```
You currently have a VStack
which contains the TabView
at the top and CustomTabBar
at the bottom. So it is no surprise, that the background of the child views do not extend behind the tab bar.
Unfortunately, a fix is not just a simple matter of moving the background to the VStack
, because each view inside a TabView
is hosted by a "container view" with a white background. If the full-screen background would be a solid color, or an image, then you could show it behind each child view and also behind the VStack
and you might not notice where the join is, but this doesn't work for a gradient (due to the different heights).
So to fix, try these changes:
VStack
, show the CustomTabBar
as an overlay over the TabView
with alignment: .bottom
.ZStack
as the container for each child view.CustomTabBar
to 60pt, so this is the size of the bottom padding that each child needs to have..ignoresSafeArea()
is applied to either the linear gradient, or to the container of each child view, otherwise the views might fail to "stick" to the bottom of the screen when switching between tabs.VStack
in your ContentView
are redundant, you can remove them.UITabBar.appearance
in init, add .toolbar(.hidden, for: .tabBar)
to each child view. For good measure, it is probably a good idea to add .toolbarBackground(.hidden, for: .tabBar)
too.Here is an adapted version of your example to show it working:
struct ContentView: View {
@State private var selectedTab: Tab = .house
@State private var isProjectScreen: Bool = false //SharedDataIsProjectScreen.sharedVariable
// init() {
// UITabBar.appearance().isHidden = true
// }
@State var isFullView:Bool = false
@State private var showSignInView: Bool = false
private var linearGradient: LinearGradient {
LinearGradient(
colors: [.yellow, .red],
startPoint: .top,
endPoint: .bottom
)
}
private var dashboard_iphone_view: some View {
ZStack {
linearGradient
.ignoresSafeArea()
Text("dashboard_iphone_view")
.padding(.bottom, 60)
}
}
private var todo_iphone_view: some View {
ZStack {
linearGradient
.ignoresSafeArea()
Text("todo_iphone_view")
.padding(.bottom, 60)
}
}
private var pomodoro_timer_iphone: some View {
ZStack {
linearGradient
.ignoresSafeArea()
Text("pomodoro_timer_iphone")
.padding(.bottom, 60)
}
}
private var Listen_View: some View {
ZStack {
linearGradient
.ignoresSafeArea()
Text("Listen_View")
.padding(.bottom, 60)
}
}
var body: some View {
VStack{
if !showSignInView {
TabView(selection: $selectedTab) {
dashboard_iphone_view
// dashboard_iphone_view(profilViewModel: ProfilViewModel(), design_selection: Design_selection())
.toolbar(.hidden, for: .tabBar)
.toolbarBackground(.hidden, for: .tabBar)
.tag(Tab.house)
todo_iphone_view
// todo_iphone_view(profilViewModel: ProfilViewModel(), design_selection: Design_selection())
.toolbar(.hidden, for: .tabBar)
.toolbarBackground(.hidden, for: .tabBar)
.tag(Tab.list)
pomodoro_timer_iphone
// pomodoro_timer_iphone(isFullView: $isFullView, profilViewModel: ProfilViewModel(), design_selection: Design_selection())
.toolbar(.hidden, for: .tabBar)
.toolbarBackground(.hidden, for: .tabBar)
.tag(Tab.clock)
Listen_View
// Listen_View(profilViewModel: ProfilViewModel(), design_selection: Design_selection())
.toolbar(.hidden, for: .tabBar)
.toolbarBackground(.hidden, for: .tabBar)
.tag(Tab.listen)
}
.overlay(alignment: .bottom) {
if isFullView == false{
CustomTabBar(selectedTab: $selectedTab)
}
}
}
}
.statusBarHidden(isFullView)
}
}
EDIT Since you are hiding the default tabbar, there would actually be a much simpler solution:
ZStack
instead of a TabView
.VStack
as the container for the main content (above) and the toolbar (below), as you were doing before.VStack
instead.var body: some View {
VStack{
if !showSignInView {
VStack {
ZStack {
if selectedTab == .house {
dashboard_iphone_view(profilViewModel: ProfilViewModel(), design_selection: Design_selection())
} else if selectedTab == .list {
todo_iphone_view(profilViewModel: ProfilViewModel(), design_selection: Design_selection())
} else if selectedTab == .clock {
pomodoro_timer_iphone(isFullView: $isFullView, profilViewModel: ProfilViewModel(), design_selection: Design_selection())
} else if selectedTab == .listen {
Listen_View(profilViewModel: ProfilViewModel(), design_selection: Design_selection())
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
if isFullView == false{
CustomTabBar(selectedTab: $selectedTab)
}
}
.background(linearGradient)
}
}
.statusBarHidden(isFullView)
}