swiftui-drawer icon indicating copy to clipboard operation
swiftui-drawer copied to clipboard

Scroll Gesture Distinction

Open maustinstar opened this issue 4 years ago • 6 comments

Problem When a ScrollView is embedded in the drawer, drags within the scroll view are used as scrolls and do not move the drawer. The current workaround is to have a larger "grabable" area at the top of the drawer.

Ideal Solution When using the maps app, there is a velocity threshold. Drags below the threshold are interpreted as scrolls, while faster drags are used to move the drawer.

Suggested by u/ms4324

maustinstar avatar Jul 15 '20 14:07 maustinstar

Edit

The maps app only scrolls when at the top height, and the drawer can only close when the scroll view is at the top.

maustinstar avatar Jul 15 '20 23:07 maustinstar

Helpful tip: I made my own custom drawer a while ago and the trick to preventing internal scroll was to first track the rested height index when dragging occurs with the following update. For your code, simply add the snippet I've flagged with a comment:

    private var dragGesture: some Gesture {
        
        return DragGesture().onChanged({ (value) in
            
            self.height = min(-value.location.y + value.startLocation.y + self.restingHeight, self.fullHeight)
            self.animation = Animation?.none
            
        }).onEnded({ (value) in
            
            let change = value.startLocation.y - value.predictedEndLocation.y + self.restingHeight
            let first = self.heights.first!
            
            self.height = self.heights.reduce((first, abs(first - change))) { (current, value) -> (CGFloat, CGFloat) in
                
                let differential = abs(value - change)
                if current.1 > differential {
                    return (value, differential)
                }
                return current
            }.0
            
            // FIND THE INDEX HERE i.e. height[0] is bottom, height[1] is middle, height[2] is top
            if let index = self.heights.firstIndex(of: self.height) {
                // SET COMBINE VARIABLE HERE FOR ENABLE SCROLL IF INDEX = 2, DISABLE OTHERWISE
                self.heightIndex = index
            }
            
            self.restingHeight = self.height
            self.animation = Animation.spring()
            DispatchQueue.main.asyncAfter(deadline: .now() + self.animationDelay) {
              self.updateAppData()
            }
        })
    }

And then disable the ScrollView when the index isn't at the position you want it to enable scrolling via some @Binding

kylebeard56 avatar Jul 16 '20 01:07 kylebeard56

@kylebeard56 thanks for the snippet! I'll look into adding it in the next update.

Thanks for the support!

maustinstar avatar Jul 17 '20 00:07 maustinstar

do you already have any plan to have this in the next update?

antranapp avatar Aug 12 '20 12:08 antranapp

@antranapp I haven't started working on this feature yet. I still have updates for the latest tag v0.0.4-beta which is focused on horizontal layouts. I plan on pushing those changes soon, and then looking into this.

I'm also thinking we can get better control of the underlying scroll view with the Introspect package https://github.com/siteline/SwiftUI-Introspect

maustinstar avatar Aug 12 '20 13:08 maustinstar

Hey there, any news on this one? Appreciate the library!

LinusGeffarth avatar Aug 09 '21 11:08 LinusGeffarth