A SwiftUI bottom-up controller, like in the Maps app. Drag to expand or minimize.
Add a dependency in your your Package.swift
.package(url: "https://github.com/maustinstar/swiftui-drawer.git", from: "0.0.3"),
Embed your view content in a ZStack
with the Drawer as the last element. The heights
parameter defines a list of resting heights for the drawer.
ZStack {
ScrollView {
//...
}
Drawer(heights: [100, 340]) {
Color.blue
}
}
Following SwiftUI's declarative syntax, these view modifiers return a modified Drawer.
Sets the haptic impact of the drawer when resting.
Feedback Style Choose from the possible impact styles. Apple Docs
public enum FeedbackStyle : Int {
/// A collision between small, light user interface elements.
case light = 0
/// A collision between moderately sized user interface elements.
case medium = 1
/// A collision between large, heavy user interface elements.
case heavy = 2
@available(iOS 13.0, *)
case soft = 3
@available(iOS 13.0, *)
case rigid = 4
}
Usage
Drawer(heights: [100, 340]) {
Color.blue
}.impact(.light)
Sets the springiness of the drawer when pulled past boundaries.
Spring Level A positive number, in pixels, to define how far the drawer can be streched beyond bounds.
A spring of 0 will not let the user drag the drawer beyond the bound of the minimum and maximum heights.
A positive spring level will allow users to pull the drawer a specified number of pixels beyond the bounds. The user's drag displacement is transformed by a logistic curve for a natural hard-spring pull that reaches an asymptote.
Default is 12px.
Usage Set a spring distance
Drawer(heights: [100, 340]) {
Color.blue
}.spring(20)
Toggle a spring distance
Drawer(heights: [100, 340]) {
Color.blue
}.spring(isSpringy ? 0 : 20)
Locks the drawer in a controlled position. When set to true, the drawer will animate into the locked height.
isLocked A Binding Bool indicating if the drawer should be locked.
height A closure returning the height to lock the drawer. The closure's argument is the drawer's current resting height.
Usage Lock into a fixed position.
Drawer(heights: [100, 340]) {
Color.blue
}.locked($locked) {_ in
return 30
}
Lock into the current resting height
Drawer(heights: [100, 340]) {
Color.blue
}.locked($locked) { (current) in
return current
}
A callback to receive updates when the drawer reaches a new resting level.
Closure This closure is executed every time the drawer reaches a new resting hieght. Use this when you want to receive updates on the drawer's changes.
Usage Lock into a fixed position.
Drawer(heights: [100, 340]) {
Color.blue
}.onRest { (restingHeight) in
print(restingHeight)
}
A multi-height drawer with haptic impact.
Drawer(heights: [100, 340, UIScreen.main.bounds.height - 40], impact: .light) {
ZStack {
RoundedRectangle(cornerRadius: 12)
.foregroundColor(.white)
.shadow(radius: 100)
VStack(alignment: .center) {
Spacer().frame(height: 4.0)
RoundedRectangle(cornerRadius: 3.0)
.foregroundColor(.gray)
.frame(width: 30.0, height: 6.0)
Spacer()
}
}
}
A basic two-height drawer.
Drawer(heights: [100, 340]) {
Color.blue
}
- Michael Verges - Initial work - mverges3@gatech.edu