How it works
A CustomPresentationDetent is a type you define to express a resting height for a presented sheet that the built-in detents — .medium and .large — can't describe. SwiftUI's presentation system snaps a sheet to one of the detents you supply; conforming to this protocol lets you add your own stopping point computed from the space currently available. Reach for it when a sheet should rest at a fraction of the screen, at a fixed point size, or at a height derived from its content, rather than at one of the standard fractions.
Conform a type to
CustomPresentationDetentA custom detent is a type — usually an empty
struct— that adopts the protocol. It carries no stored state; it exists purely to vend a height. In the example,ThirdHeightconforms toCustomPresentationDetentand serves as the named identity for that resting position.Implement the
height(in:)requirementThe protocol's single requirement is the static method
height(in:), which SwiftUI calls to ask how tall the sheet should be. Returning aCGFloatfixes the height in points; returningniltells SwiftUI to ignore this detent for the current context. Hereheight(in:)returnscontext.maxDetentValue / 3to rest at a third of the available space.Read the layout from
ContextThe
in context:parameter is aCustomPresentationDetent.Contextdescribing the environment in which the height is being resolved. ItsmaxDetentValuereports the largest height a detent may occupy — effectively the room a.largedetent would take — so you can compute proportional heights against it, as the example does withcontext.maxDetentValue / 3.Register the detent with
.custom(_:)A custom detent reaches a sheet by being wrapped in the
PresentationDetent.custom(_:)case, which takes the conforming type itself. PassingThirdHeight.selfto.custom(ThirdHeight.self)turns your type into aPresentationDetentvalue that the presentation system understands.Offer it through
presentationDetents(_:)The set of allowed resting positions is declared on the sheet's content with the
presentationDetents(_:)modifier, which accepts an array ofPresentationDetentvalues. In the example.presentationDetents([.custom(ThirdHeight.self)])makes the one-third height the sole detent the sheet can settle on.
context.maxDetentValue / 3 in height(in:) to context.maxDetentValue * 0.8 and the sheet will rest much higher, showing that the returned CGFloat directly sets the detent's height.Example & preview
Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.
struct CustomPresentationDetentDemo: View {
struct ThirdHeight: CustomPresentationDetent {
static func height(in context: Context) -> CGFloat? {
context.maxDetentValue / 3
}
}
@State private var showSheet = true
var body: some View {
Color.clear
.sheet(isPresented: $showSheet) {
VStack(spacing: 12) {
Text("Custom Detent")
.font(.headline)
Text("Resting at one third of the available height.")
.multilineTextAlignment(.center)
}
.padding()
.presentationDetents([.custom(ThirdHeight.self)])
}
.padding()
}
}