Sheets, Half Sheets & more with Presentation Detents in SwiftUI
Duncan Kent
Posted on September 20, 2022
Apple added Detents to their Presentation Containers in WWDC2022, in order to provide more flexibility among various parts of your app's view hierarchy.
The new PresentationDetent struct comes with 2 included properties:
-
medium
- the sheet takes up approximately half of the device's screen -
large
- the sheet covers the entire screen
medium
large
These detents can be implemented using the .presentationDetents modifier on a sheet. You can choose to include multiple options using a Set of type PresentationDetent.
.sheet(isPresented: $sheetPresented) {
SheetView()
.presentationDetents([.medium, .large])
}
There are a few documented methods also, that allow for greater flexibility when using sheet.
This means that it would be very straightforward to create the /bottom drawer/ effect that is becoming more popular in apps using the following two methods:
fraction - allows you to specify a fractional height (of the screen)
height- specify a height that your sheet will occupy (relative to the bottom of the screen)
Both methods use the type CGFloat, and can be assigned to variables and changed programmatically, altering the placement of your sheet each time it appears in the app session.
A custom PresentationDetent can be created which must conform to the protocol CustomPresentationDetent . In this example, I have created a detent specifically to act in a "drawer" presentation style.
DrawerDetent Struct and Extension to PresentationDetent
private struct DrawerDetent: CustomPresentationDetent {
static func height(in context: Context) -> CGFloat? {
max(80, context.maxDetentValue * 0.15)
}
}
extension PresentationDetent {
static let drawer = Self.custom(DrawerDetent.self)
}
Calling this on the view, with the appropriate modifier:
.sheet(isPresented: $sheetPresented)
SheetView()
.presentationDetents([.drawer])
}
Drawer Style Sheet Result:
If you'd prefer to have a range of different sizes, and allow the user a lot more control over the placement of the sheet, you can include many options in the .presentationDetents Set.
let heights = stride(from: 0.2, through: 1.0, by: 0.2).map {
PresentationDetent.fraction($0)
}
.sheet(isPresented: $sheetPresented) {
SheetView()
.presentationDetents(Set(heights))
}
Lastly, you can combine these previous examples, for even more bespoke sheet options using the union function of Set:
SheetView()
.presentationDetents(Set(heights).union([.drawer, .medium]))
Posted on September 20, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 29, 2024