Home > OS >  (SwiftUI) can anyone tell me why my NavigationView is creating extra NavigationBars and blank space
(SwiftUI) can anyone tell me why my NavigationView is creating extra NavigationBars and blank space

Time:02-11

I have an app with 3 views. they are connected by a NavigationView and have NavigationLinks that link to the next view. however, all views are created with an extra NavigationBar and with lots of blank white space on the bottom that travels up the screen every time you click through the views and go back to the home page. I remember a few days ago having this issue when I went from the HomeView() to the TimerView() but I'm not sure how I got rid of it. and also I definitely did not get rid of it because I'm still having the same problem. and also I don't remember how I worked around this the first time. I have seen other posts which say I should set the navigationBar color to clear but that does nothing. not sure what is going on. most other posts on this topic are about removing the space up top and very few talk about the blank space on the bottom so I'm not really sure what to do.

I go into the capture view hierarchy and I see that white footer bar is created when the view is created but then just seems to stack on top of every other view until the application is unusable. using Xcode 13.1 and running in simulator on iPhone 12 with iOS 15.0.

here's the video as well as pictures from the capture view hierarchy thing https://imgur.com/a/jBprYbN

and here's the code

struct ContentView: View {

    @State private var selectedTab = 0
    let numTabs = 2
    let minDragTranslationForSwipe: CGFloat = 50
    @State var secondScreenShown = true

    @State private var tabSelection = 0
    @State private var tappedTwice:Bool = false
    @State private var homeID = UUID()
    var handler: Binding<Int> { Binding (
        get: {self.tabSelection},
        set: {
            if $0 == self.tabSelection {
                tappedTwice = true
                print("tappedTwice = true")
            }
            self.tabSelection = $0
        }

    )}


    init() {
        UITabBar.appearance().isTranslucent = false
    }

    var body: some View {
        TabView(selection:handler) {
            NavigationView {
            HomeView()
                .id(homeID)
                .tabItem {
                  Label("Home", systemImage: "house.fill")
                }.tag(0)
                .onChange(of: tappedTwice, perform: { tappedTwice in
                    guard tappedTwice else { return }
                    homeID = UUID()
                    self.tappedTwice = false
                })
            }

        }
        .edgesIgnoringSafeArea(.all)
        .frame(
            minWidth: UIScreen.main.bounds.width,
            maxWidth: .infinity,
            minHeight: UIScreen.main.bounds.height,
            maxHeight: .infinity,
            alignment: .center
        )
    }
}

here's the HomeView()

    struct HomeView: View {

    @State var secondScreenShown = false
    @State var timerVal = 1
    @State private var chosenSound = "None"
    var times = [1, 2, 3, 4, 5, 10, 15, 20, 30, 45, 60]
    var sounds = ["None", "Creepy Kids", "Conjuring The Dark Ones", "The Forbidden Forest" ]
    
    init() {
        UITableView.appearance().tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: Double.leastNonzeroMagnitude))
        UITableView.appearance().tableFooterView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: Double.leastNonzeroMagnitude))
    }
    
    var body: some View {
 //       NavigationView {
            VStack {
                VStack {
                            VStack {
                                Group {
                                    VStack {
                                    
                                                NavigationLink(
                                                    destination: TimerView(timerScreenShown: $secondScreenShown, timerVal: timerVal, chosenSound: chosenSound, initialTime: timerVal),
                                                    isActive: $secondScreenShown,
                                                    label: {Text("Go")
                                                        
                                                        .font(.title2)
                                                        .padding()
                                                        .frame(minWidth: 250)
                                                        .overlay(
                                                            Capsule(style: .continuous)
                                                                .stroke(Color.black, lineWidth: 3)
                                                        )
                                                    })
                                                    .frame(minWidth: /*@START_MENU_TOKEN@*/0/*@END_MENU_TOKEN@*/, maxWidth: 100, alignment: .bottom)
                                                    .padding(.top, 10)
                                        
                                    
                                } // third group
                            }
                    
                } // VStack just outside rectangle
                .frame(
                    maxWidth: .infinity,
                    minHeight: UIScreen.main.bounds.height,
                    maxHeight: .infinity,
                    alignment: .center
                )
                .padding()
 //               ) // rectangle.overlay()
                
            } // VStack
            .edgesIgnoringSafeArea([.top, .bottom])
            .background(Color.pink)
            .frame(
                minWidth: UIScreen.main.bounds.width,
                maxWidth: .infinity,
                minHeight: UIScreen.main.bounds.height,
                maxHeight: .infinity,
                alignment: .center
            )

     //   } // NavigationView
        .navigationViewStyle(StackNavigationViewStyle())
        .navigationBarTitle("main level")
    }
}
}

And here's the TimerView()

    struct TimerView: View {

    @Binding var timerScreenShown:Bool
    @State var timerVal:Int
    @State var chosenSound:String

    @State private var showNextView = false
    @State private var paused = false

    var initialTime:Int

    let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

    var body: some View {
        
        VStack {
            VStack {
                        VStack {
                                NavigationLink(
                                    destination: HomeView(),
                                    label: {Text("Home Page")})
                                        .font(.title2)
                                        .frame(minWidth: 0,maxWidth: 200, alignment: .center)
                                        .overlay(
                                            Capsule(style: .continuous)
                                                .stroke(Color.black, lineWidth: 3)
                                        )
                                        .padding(.top, 35)

                            //    } // else
                        } // innermost VStack

                        .frame(
                            alignment: .center
                        )
                        .padding()
  //              )

            } // VStack 2
            .frame(
                minWidth: UIScreen.main.bounds.width,
                maxWidth: .infinity,
                minHeight: UIScreen.main.bounds.height,
                maxHeight: .infinity,
                alignment: .center
            )

        } // VStack
        .edgesIgnoringSafeArea([.top, .bottom])
        .background(Color.purple
//            Image("HomePageBackground")
//                .resizable()
//                .ignoresSafeArea()
        )
        .frame(
            minWidth: UIScreen.main.bounds.width,
            maxWidth: .infinity,
            minHeight: UIScreen.main.bounds.height,
            maxHeight: .infinity,
            alignment: .center
        )

        .onAppear(){
            UITableView.appearance().tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: Double.leastNonzeroMagnitude))
            UITableView.appearance().tableFooterView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: Double.leastNonzeroMagnitude))
        }

        .navigationBarTitle("timer view")
    } // View

}

so yeah it's obvious there's extra navigation views being created somewhere but I'm not sure where. it's also obvious that blank space in the footer is created when the view is loaded but I don't know where. so yeah any help would be appreciated.

if there are any brackets/parenthesis missing it's because I accidentally deleted it while removing commented out extraneous code.

CodePudding user response:

The issue is caused by the UITabBar.appearance().isTranslucent = false line -- without that, as you confirmed in the comments, it behaves as expected.

Here's a working version with a note about that line:

import SwiftUI

struct ContentView: View {
    
    init() {
        UITabBar.appearance().isTranslucent = false //REMOVE THIS and functionality will be as-expected
    }
    
    var body: some View {
        TabView {
            NavigationView {
                HomeView()
            }.tabItem {
                Label("Home", systemImage: "house.fill")
            }
            .navigationViewStyle(StackNavigationViewStyle())
            .tag(0)
        }
    }
}

struct TimerView: View {
    var body: some View {
        VStack {
            NavigationLink(
                destination: HomeView(),
                label: {Text("Home Page")})
        }
        .padding()
        .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
        .background(Color.purple)
        .edgesIgnoringSafeArea([.top, .bottom])
        
        .navigationBarTitle("timer view")
    }
    
}

struct HomeView: View {
    var body: some View {
        VStack {
            NavigationLink(
                destination: TimerView(),
                label: {
                    Text("Go")
                })
                .frame(minWidth: 0, maxWidth: 100, alignment: .bottom)
                .padding(.top, 10)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.pink)
        .edgesIgnoringSafeArea([.top, .bottom])
        .navigationBarTitle("main level")
    }
}
  • Related