简体   繁体   中英

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.

Following to apply throughout the application

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

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

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

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM