In WWDC 22, Apple introduced resizable bottom sheet for SwiftUI 4 with a newly introduced modifier called presentationDetents.
Prior iOS 16, expandable bottom sheet was done by porting over UISheetPresentationContoller from UIKit to SwiftUI but now with presentationDetents bottom sheet is natively supported.
presentationDetents modifier accepts a collection of detents for sheet and we use this new modifier by simply adding it inside the sheet view.
Let’s take an example, for our example we will set the detent to .medium which will shows a bottom sheet that will take up half of the screen.
struct ContentView: View {
@State private var presentSheet = false
var body: some View {
VStack {
Text("DevTechie!")
.font(.largeTitle)
.foregroundColor(.primary)
Button("Show Sheet") {
presentSheet.toggle()
}
.buttonStyle(.borderedProminent)
.sheet(isPresented: $presentSheet) {
Text("This is a bottom sheet")
.presentationDetents([.medium])
}
}
.padding()
}
}
Note that presentationDetents modifier is applied inside the Sheet view on the Sheet view.
If we need to make this sheet resizable, we will have to supply more than one detent inside the presentationDetentsmodifier. Let’s pass medium and large detents to our example:
struct ContentView: View {
@State private var presentSheet = false
var body: some View {
VStack {
Text("DevTechie!")
.font(.largeTitle)
.foregroundColor(.primary)
Button("Show Sheet") {
presentSheet.toggle()
}
.buttonStyle(.borderedProminent)
.sheet(isPresented: $presentSheet) {
Text("This is a bottom sheet")
.presentationDetents([.large, .medium])
}
}
.padding()
}
}
With this new change, notice that we now have a drag bar indicating which indicates that the sheet is resizable.
If we want to hide the drag indicator, we can do that by adding presentationDragIndicator modifier and setting it to .hidden
struct ContentView: View {
@State private var presentSheet = false
var body: some View {
VStack {
Text("DevTechie!")
.font(.largeTitle)
.foregroundColor(.primary)
Button("Show Sheet") {
presentSheet.toggle()
}
.buttonStyle(.borderedProminent)
.sheet(isPresented: $presentSheet) {
Text("This is a bottom sheet")
.presentationDetents([.large, .medium])
.presentationDragIndicator(.hidden)
}
}
.padding()
}
}
Other than the preset detents such as .medium,or .large we can also create a custom detent using .fraction.
.fraction takes a value between 0 and 1 representing 0 to 100% of screen height. We will apply three fraction values, 25%, 50% and 75% for our example:
struct ContentView: View {
@State private var presentSheet = false
var body: some View {
VStack {
Text("DevTechie!")
.font(.largeTitle)
.foregroundColor(.primary)
Button("Show Sheet") {
presentSheet.toggle()
}
.buttonStyle(.borderedProminent)
.sheet(isPresented: $presentSheet) {
Text("This is a bottom sheet")
.presentationDetents([
.fraction(0.25),
.fraction(0.5),
.fraction(0.75)])
}
}
.padding()
}
}
We also have option to supply .height as a parameter which sets the height of bottom sheet.
struct ContentView: View {
@State private var presentSheet = false
var body: some View {
VStack {
Text("DevTechie!")
.font(.largeTitle)
.foregroundColor(.primary)
Button("Show Sheet") {
presentSheet.toggle()
}
.buttonStyle(.borderedProminent)
.sheet(isPresented: $presentSheet) {
Text("This is a bottom sheet")
.presentationDetents([
.height(100),
.height(300),
.height(500)])
}
}
.padding()
}
}
With that we have reached the end of this article. Thank you once again for reading. Subscribe to our weekly newsletter at https://www.devtechie.com