Logo for tanaschita.com

How to build a draggable bottom sheet with a scroll view in SwiftUI

Learn how to build a bottom sheet such as in Apple Maps or Google Maps with SwiftUI

11 Mar 2024 · 5 min read

Some apps such as Apple Maps or Google Maps are using a draggable bottom sheet to allow users to quickly switch between the parent view such as a map and the content which is visible in the sheet, often embedded in a scroll view.

Example of a draggable bottom sheet.

In this article, we are going to look at how to build such a draggable bottom sheet with a scroll view in SwiftUI.

Let's directly jump in.

Sponsorship logo
Preparing for a technical iOS job interview - updated for iOS 17
Check out my book on preparing for a technical iOS job interview with over 200 questions & answers. Test your knowledge on iOS topics such as Swift, SwiftUI, Combine, HTTP Networking, Authentication, SwiftData & Core Data, Concurrency with async/await, Security, Automated Testing, Machine Learning and more.
LEARN MORE

To be more concrete, what we'd like to achieve is:

  • the sheet has multiple states such as collapsed, medium-opened and expanded
  • the sheet is not fully dismissable by user interaction
  • the user can interact with the contents of the parent view such as the map
  • the dragging works together with a scroll view which is used inside the sheet to show content

We can implement the described behaviour by using SwiftUI's sheet combined with presentationDetents which are available starting with iOS 16.4:

struct ContentView: View {
@State private var showingBottomSheet = true
var body: some View {
MapView()
// 1.
.sheet(isPresented: $showingBottomSheet) {
ScrollView {
// Add content of the bottom sheet here.
}
// 2.
.interactiveDismissDisabled()
// 3.
.presentationDetents([.height(50), .medium, .large])
// 4.
.presentationBackgroundInteraction(
.enabled(upThrough: .large)
)
}
}
}

Let's look step-by-step at what happens in the code above:

  1. We create a sheet with a state variable showingBottomSheet set to true
  2. We use .interactiveDismissDisabled() to disable dismissal of the sheet by swiping it down
  3. We use .presentationDetents([.height(50), .medium, .large]) to setup the different states of the sheet when user drags it down and up
  4. We use .presentationBackgroundInteraction() to allow user interaction with the parent view when the sheet is not fully opened.

And that's basically it. We can implement a draggable bottom sheet with a few lines of code.

One downside you may run into is that a sheet is always shown above the whole view hierarchy - which means that it also covers tab bars. For now, there is no hands-on solution to, for example, show a tab bar above that sheet. We could use a multiple windows approach but a solution like that adds quite a lot to the complexity.

Sponsorship logo
Preparing for a technical iOS job interview - updated for iOS 17
Check out my book on preparing for a technical iOS job interview with over 200 questions & answers. Test your knowledge on iOS topics such as Swift, SwiftUI, Combine, HTTP Networking, Authentication, SwiftData & Core Data, Concurrency with async/await, Security, Automated Testing, Machine Learning and more.
LEARN MORE

Newsletter

Image of a reading marmot
Subscribe

Like to support my work?

Say hi

Related tags

Articles with related topics

swiftui

performance

swift

ios

How to avoid using AnyView in SwiftUI

By using alternatives such as the @ViewBuilder attribute, Group type or generics.

01 Apr 2024 · 6 min read

Latest articles and tips

© 2024 tanaschita.com

Privacy policy

Impressum