TEAM LICENSES: Save money and learn new skills through a Hacking with Swift+ team license >>

How do I embed a ScrollView in a NavigationStack?

Forums > Swift

Hello,

I am having trouble embedding a ScrollView in a NavigationStack or NavigationView. The ScrollView does not extend to the bottom of the screen. If I remove the NavigationStack the ScrollView works as expected. I have added .ignoresSafeArea() and .ignoresSafeArea(edges: .all) on both the ScrollView and the NavigationStack and tried wrapping the ScropllView in a ZStack, but nothing seems to change the behavior.

Does anyone have any advice on how this can. be done or what i can try?

I have attached a link that shows the issue. Thanks for any help!!!

Here is my View:

    var body: some View
    {
        NavigationStack {
            ScrollView {
                let columns = [
                    GridItem(.fixed(imageWidth), spacing: colEndPadding),
                    GridItem(.fixed(imageWidth), spacing: colEndPadding),
                    GridItem(.fixed(imageWidth), spacing: colEndPadding)
                ]
                LazyVGrid(columns: columns, spacing: colEndPadding) {
                    ForEach(0..<18, id: \.self) { index in
                        Rectangle()
                            .foregroundColor(Color(
                                red: .random(in: 0...1),
                                green: .random(in: 0...1),
                                blue: .random(in: 0...1),
                                opacity: 1.0
                            ))
                            .frame(width: imageWidth, height: imageHeight)
                    }
                }
                .padding(.horizontal)
            }
            .edgesIgnoringSafeArea(.all)
            .navigationBarHidden(false)
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Menu(content: {
                        MoreMenuButtonTextWithImage(label: "Option 1", systemImageName: "folder.badge.plus") { }
                        MoreMenuButtonTextWithImage(label: "Option 2", systemImageName: "folder.badge.plus") { }
                        MoreMenuButtonTextWithImage(label: "Option 3", systemImageName: "folder.badge.plus") { }

                        Divider()

                        MoreMenuButtonText(label: "Option A") { }
                        MoreMenuButtonText(label: "Option B") { }
                        MoreMenuButtonText(label: "Option C") { }
                    }, label: {
                        Image(systemName: "ellipsis.circle")
                            .foregroundColor(Color("allstar_Ice"))
                    })
                }
            }
            .navigationBarTitleDisplayMode(.inline)
            .toolbarBackground(.visible, for: .navigationBar)
        }
        .edgesIgnoringSafeArea(.all)
        .background(
            GeometryReader { geometry in
                Color.clear
                    .onAppear {
                        let screenWidth: CGFloat = geometry.size.width
                        let cols = 3.0
                        imageWidth = (screenWidth - (colEndPadding * (cols - 1))) / 3
                        imageHeight = (((screenWidth - (colEndPadding * (cols - 1))) / 3) * 16) / 9
                        Self.log.info("Line: \(#line), File: \(#file), Function: \(#function): \(#file):\(#function):\(#line), *** imageWidth=\(imageWidth), imageHeight=\(imageHeight)")
                    }
            }
        )
    }

1      

I'm not sure if I understand the issue however done this. Works fine

struct ContentView: View {
    let columns = Array(repeating: GridItem(.flexible(), spacing: 3), count: 3)

    var body: some View {
        TabView {
            NavigationStack {
                ScrollView {
                    LazyVGrid(columns: columns, spacing: 3) {
                        ForEach(0..<18, id: \.self) { _ in
                            Rectangle()
                                .foregroundStyle(
                                    Color(
                                        red: .random(in: 0...1),
                                        green: .random(in: 0...1),
                                        blue: .random(in: 0...1),
                                        opacity: 1.0
                                    )
                                )
                                .containerRelativeFrame(.vertical) { size, axis  in // <- use this for the height
                                    size * 0.3
                                }
                        }
                    }

                }
                .padding(.horizontal)
                .navigationBarTitleDisplayMode(.inline)
                .toolbar {
                    Button("Menu Button here", systemImage: "ellipsis.circle") { }
                }
            }
            .tabItem { Label("Example", systemImage: "house") }
        }
    }
}

1      

Yes, thank you. I should have tried it in a new project. It turns out I am doing this nmy init and for some reason one of these is causing the issue. I will investigate more, but I am all set now:

    init() {
        UITabBar.appearance().isHidden = false
        UITabBar.appearance().backgroundColor = UIColor(named: "midnightDark")
        UITabBar.appearance().unselectedItemTintColor = UIColor(named: "chalkAlpha45")
        UITabBar.appearance().isTranslucent = false
        UITabBar.appearance().barTintColor = UIColor(named: "midnightDark")
    }

1      

Hacking with Swift is sponsored by Blaze.

SPONSORED Still waiting on your CI build? Speed it up ~3x with Blaze - change one line, pay less, keep your existing GitHub workflows. First 25 HWS readers to use code HACKING at checkout get 50% off the first year. Try it now for free!

Reserve your spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.