I've come across a UI component in iPadOS that behaves like a modal with detents, but I'm uncertain about its name or how to properly implement it. It appears to exhibit detent-like behavior, but when attempting to employ a sheet with detents, it doesn't function as expected on iPad.
Could someone please assist me in identifying this component within the iPadOS framework? Additionally, I'm curious whether it's specific to UIKit or if it can be utilized in SwiftUI as well. Any clarification or guidance on effectively using this component, especially with detents, would be greatly appreciated. Thank you.
I don't know if there's some native component which resembles a sheet but, you can achieve something really similar really simply with SwiftUI:
struct ContentView: View {
@State var isOpen = true
var body: some View {
NavigationStack {
GeometryReader { proxy in
let size = proxy.size
ZStack {
Map()
CustomMapSheet(size: size)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
@ViewBuilder
func CustomMapSheet(size: CGSize) -> some View {
ZStack(alignment: .leading) {
VStack {
Text("Content Here")
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.overlay(alignment: .top) {
Capsule()
.frame(width: 50, height: 4)
.padding(.top)
.clipShape(.rect)
.gesture(
DragGesture()
.onChanged({ value in
let predictedY = value.predictedEndTranslation.height
if predictedY > 400 {
withAnimation(.snappy) {
isOpen = false
}
} else if predictedY < 150 {
withAnimation(.snappy) {
isOpen = true
}
}
})
)
}
}
.background(.thickMaterial, in: .rect(cornerRadius: 15, style: .continuous))
.padding()
.frame(width: size.width / 2.8, height: isOpen ? size.height : size.height / 8) // <-- This is for the size
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading) // <-- This is to Position it to the leading side
.offset(y: isOpen ? 0 : (size.height - size.height / 2) - 40) // To take it to the bottom when closed
}
}
And there you have it
Of course you can improve it in multiple ways, but I think it's a good starting point. Let me know your thoughts!