Wednesday, September 28, 2022
HomeiOS Developmentios - SwiftUI ScrollView gesture recogniser

ios – SwiftUI ScrollView gesture recogniser


How can I detect when a ScrollView is being dragged?

Inside my ScrollView I’ve an @Binding scrollPositionOffset variable that I watch with .onChange(of:) after which programmatically scroll to that place utilizing ScrollViewReader.scrollTo(). This works nice, however I must additionally replace scrollPositionOffset once I scroll the ScrollView straight. I am struggling to do this as this is able to set off the .onChange(of:) closure and get right into a loop.

My answer is to conditionally name ScrollViewReader.scrollTo() solely when I’ve a localScrolling variable set to false. I’ve tried to set this utilizing DragGesture.onChanged and .onEnded, however this is not the identical because the drag gesture that causes the scroll, so .onEnded by no means fires.

What I believe I want is a @GestureRecognizer for ScrollView much like UIScrollView’s isDragging or isTracking (I am conscious I might use UIScrollView, however I do not know the way, and that looks as if it is perhaps extra work!! I might settle for a solution that reveals me find out how to drop that right into a SwiftUIView too)

Context (in case anybody has a cleaner answer to my precise situation):

I’ve a ScrollView that I am programmatically scrolling to create an impact just like the Minimap view inside Xcode (i.e. I’ve a zoomed-out view adjoining to the ScrollView, and dragging the minimap causes the ScrollView to scroll).

This works nice once I use the minimap, however I am struggling to get the reverse to occur: shifting the place of the ScrollView to replace the minimap view.

Code


@Binding var scrollPositionOffset: CGFloat
let zoomMultiplier:CGFloat = 1.5

 var physique: some View{
        
        ScrollViewReader { scrollViewProxy in
            GeometryReader{ geometry in
                ScrollView {
                    ZStack(alignment:.high){

         //The content material of my ScrollView

                    MagnifierView()
                        .body(peak: geometry.dimension.peak * zoomMultiplier)
                    
         //I am utilizing this as my offset reference

                        Rectangle()
                            .body(peak:10)
                            .alignmentGuide(.high) { _ in
                                geometry.dimension.peak * zoomMultiplier * -scrollPositionOffset
                            }
                            .id("scrollOffset")    
                    }
                }
                .onAppear(){
                    scrollViewProxy.scrollTo("scrollOffset", anchor: .high)
                }
                
                .onChange(of: scrollPositionOffset, carry out: { _ in
            
        //Solely name .scrollTo() if the view is not already being scrolled by the person

                    if !localScrolling {
                    scrollViewProxy.scrollTo("scrollOffset", anchor: .high)
                    }
                    
                })
                
                .gesture(
                    DragGesture()
                        .onChanged{gesture in
                            localScrolling = true
                            
                            let offset = gesture.location.y/(zoomMultiplier * geometry.dimension.peak)

                            scrollPositionOffset = offset
                        }
        
                        .onEnded({gesture in

     //Would not ever fireplace when scrolling

                            localScrolling = false
                        })
                )
            }
        }
    }

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments