GO FURTHER, FASTER: Try the Swift Career Accelerator today! >>

Choosing to display one or other ScrollView blocks the second one

Forums > SwiftUI

Hello !

I have a particular issue where, when using two ScrollViews and trying to display one or the other conditionnally, the second one never works.

To make it simple : I need to display a list, but if a certain action is made, I need to display a second different list instead (not filtering, a whole other data type and cells). When the condition to display the second ScrollView is active, I see the second ScrollView. But :

  • I can't scroll at all unless I go back to the first ScrollView
  • In the same manner, buttons inside the second ScrollView doesn't work

It seems like the user interaction is disabled on the second scroll view. I tried to inverse the condition, to see if there was a problem with the second layout, but the issue remains: it's always the scrollview that comes second that doesn't work.

Here's the current code for the view:

struct SearchView: View {

    @StateObject var viewModel: SearchViewModel

    var body: some View {
        ZStack(alignment: .top) {
            ScrollView {
                LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 2), spacing: 16) {
                    ForEach(viewModel.categories, id: \.id) { category in
                        Button {
                            viewModel.categoryTapped(category: category)
                        } label: {
                            CategoryCellView(category: category)
                        }
                    }
                }
                .padding(.horizontal, 16)
            }
            .opacity(viewModel.items.isEmpty ? 1 : 0)

            ScrollView {
                LazyVStack {
                    ForEach(viewModel.items) { item in
                        Button {
                            viewModel.openItem(item: item)
                        } label: {
                            cell(for: item)
                        }
                    }
                }
                .padding(.horizontal, 16)
            }
            .opacity(viewModel.items.isEmpty ? 0 : 1)
        }
        .onAppear {
            viewModel.load()
        }
    }

In this version, I'm trying to display both ScrollView but hide one with opacity, but it's because I tried so many things already. Same result with an if/else condition determining which scroll views is displayed, same result by setting the if/else condition inside an unique ScrollView, same result by setting the if/else inside the LazyVGrid.

If someone has an idea, it will be glady appreciated! thanks

   

Try to use another approach. Instead of using two separate ScrollViews, use LazyVGrid or LazyVStack depending on condition. So there will be only one ScrollView but different data layout inside that.

   

I tried this before but unfortunately, it still doesn't work. Exact same issue: once the second list is displayed, no user interaction work, meaning openItem(item: item) doesn't do anything, and it doesn't scroll at all.

struct SearchView: View {

    @StateObject var viewModel: SearchViewModel

    var body: some View {
        ZStack(alignment: .top) {
            ScrollView {
                if viewModel.items.isEmpty {
                    LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 2), spacing: 16) {
                        ForEach(viewModel.categories, id: \.id) { category in
                            Button {
                                viewModel.categoryTapped(category: category)
                            } label: {
                                CategoryCellView(category: category)
                            }
                        }
                    }
                    .padding(.horizontal, 16)
                } else {
                    LazyVStack {
                        ForEach(viewModel.items) { item in
                            Button {
                                viewModel.openItem(item: item)
                            } label: {
                                cell(for: item)
                            }
                        }
                    }
                    .padding(.horizontal, 16)
                }
            }
        }
        .onAppear {
            viewModel.load()
        }
    }
}

   

Not sure if this is the case, but you might give it a try. @StateObject var viewModel: SearchViewModel if you're passing the object and want to observe it, it should be marked as @ObservedObject instead. Too many things may affect the code run, without more or less full picture what is going on, it is difficult to say.

   

Hacking with Swift is sponsored by RevenueCat.

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's all new Paywall Editor allow you to remotely configure your paywall view without any code changes or app updates.

Click to save your free 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.