blrsk
blrsk

Reputation: 345

SwiftUI: ScrollView that drags bottom sheet with it

I'm trying to create a SwiftUI Scrollview that drags its container like this: https://drive.google.com/file/d/1O92DgsVI1OjM1HEUXUwVywB8gcdShOP-/view?usp=sharing

Many Apple apps use this (Apple Maps, Music, Wallet, etc) but I haven't found an easy way to do it wit SwiftUI. What do you think is the best way to implement this simply?

I've looked at most libraries here https://github.com/search?q=swiftui+drawer but none of them implements their drawer with a ScrollView in it that can drag the view.

I also tried implementing a custom UIScrollView as UIViewRepresentable and I tried to tweak the scrollViewWillBeginDragging() but I could not make it work.

Upvotes: 5

Views: 5202

Answers (6)

Beau Nouvelle
Beau Nouvelle

Reputation: 7252

As of iOS 16.4 you now have access to this modifier:

.presentationContentInteraction(.scrolls)

One of those 'you need to know about it to use it' things since I personally tried using code complete with terms like "drag" and "swipe" etc with no results.

Upvotes: 0

Protocol
Protocol

Reputation: 1792

struct ContentView: View {
    init() {
        UIScrollView.appearance().bounces = false
    }
    var body: some View {
        ZStack {
            DraggableView()
            ScrollView {
                LazyVStack {
                    Text("Hello World")
                }
            }
        }
    }
}

Upvotes: -1

Bruno Fulber Wide
Bruno Fulber Wide

Reputation: 512

Ok, I ran into this problem while developing a drawer package myself, and I believe I was able to solve it using the legacy UIscrollView and a UIViewRepresentable wrapper.

if you want to use the packages you already had before, here's I ended up doing:

inside my Drawer, I've added this LegacyScrollView wrapper.

    LegacyScrollView(.vertical, showsIndicators: showsIndicators) {
        content
    }
    .onDragShouldBegin { pan, scrollView in
        /// touch shouldn't begin when scrolling past zero content offset
        scrollView.contentOffset.y - pan.translation(in: scrollView).y > 0
    }

with this wrapper I'm able to access UIScrollView's gestureRecognizerShouldBegin(_:) and override it through a SwiftUI modifier

Result

Upvotes: 3

Andrew Mejia
Andrew Mejia

Reputation: 11

I've ran into the same issue and came across the FloatingPanel package. The repo includes an example to apply it to SwiftUI apps.

Upvotes: 1

Eugene Dudnyk
Eugene Dudnyk

Reputation: 6030

Check the SheeKit library where that behaviour is supported for native sheets.

You can read about the implementation in this story on medium. Also, you can find the demo video in the end of the story.

In case if you need an advanced native SwiftUI scroll view with the support of content offset tracking and other UIKit-like configurability, check the SolidScroll library and the story behind it.

Upvotes: 0

Virat
Virat

Reputation: 43

Following is used to apply throughout the application

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    UIScrollView.appearance().bounces = false
}

Upvotes: 0

Related Questions