0

I'm trying to implement an app where one of the views is a list with many elements. Thus it must be able to scroll. On the toolbar I have a switch to conditionally apply a ViewModifier that displays the same list and a Rectangle() in an HStack.

My problem is that if the list on the main view is scrolled, this scrolling is not applied to the list in the ViewModifier:

Quick visual demo

As you can see, the scrolling of the list in the main View and in the ViewModifier is each time reset to the top.

The main view:

struct ContentView: View {
    @State private var isPresentingViewModifier = false
    var body: some View {
        NavigationStack {
            List {
                ForEach(1...30, id: \.self) {
                    Text("ListItem \($0)")
                }
            }
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing){
                    Button(action: {
                        isPresentingViewModifier = true
                    }) {
                        Text("Flip")
                    }
                }
            }
        }
        .conditionalModifier(isPresentingViewModifier, myViewModifier(onFinished: {
            isPresentingViewModifier = false
        }))
    }
}

The ViewModifier:

struct myViewModifier: ViewModifier {
    var onFinished: () -> ()
    func body(content: Content) -> some View {
        HStack {
            content
            Rectangle()
                .fill(.black.opacity(0.5))
                .onTapGesture {
                    onFinished()
                }
        }
    }
}

And the View extension that allows to conditionally apply the ViewModifier:

extension View {
    public func conditionalModifier<T>(_ condition: Bool, _ modifier: T) -> some View where T: ViewModifier {
        Group {
            if condition {
                self.modifier(modifier)
            } else {
                self
            }
        }
    }
}

I've tried to use a ScrollViewReader to get the scrolling position and then apply it the ViewModifier's content, but it didn't work. I've also tried to set a GeometryReader in the list like that:

    var body: some View {
            NavigationStack {
                List {
                    // [...]
                    .background(GeometryReader { geometry in
                        Color.clear.preference(key: ScrollOffsetPreferenceKey.self, value: geometry.frame(in: .named("scroll")).origin)
                    })
                    .onPreferenceChange(ScrollOffsetPreferenceKey.self) { value in
                        GlobalVariables.scrollPosition = value
                    }
                }
            }
        .conditionalModifier(isPresentingHelpView, ShowCaseRoot(showHighlights: true, onFinished: {
            isPresentingHelpView = false
        }))
    }

The 'scrollPosition' is correctly read but I don't find a way to apply it to the ViewModier's content.

Thank you in advance for any help that would allow me to apply the scrolling position of the list in the main view to the list in its ViewModifier.

Y4nn
  • 1
  • 1

0 Answers0