I recently wrote about bottom sheets in SwiftUI while working on my Meshing app. I realized I had been experimenting with hardcoded fractions to control when to show "detailed" controls. It felt clunky and inflexible. Also, I needed more control over the bottom sheet, especially the presentation detents detection.
I randomly stumbled upon another modifier for it: presentationDetents(_ detents: Set<PresentationDetent>, selection: Binding<PresentationDetent>)
and excited to share what I have learned. Let's explore how to detect and control bottom sheet positions in SwiftUI!
Creating an Enum for Sheet Positions
I like enumerations, so I created a custom enum for sheet positions. This approach keeps the code clean and makes it easy to adjust fraction values in one place:
In this enum, peek
represents the minimized sheet (10% of the screen height), and detailed
is the expanded view (50% of the screen height). The detent
computed property converts the cases to PresentationDetent
values.
Implementing the Selection Modifier
With the enum in place, I used the newly discovered presentationDetents(_:selection:)
modifier to control the sheet position. This modifier gave me programmatic control over the currently selected detent:
I have the static allDetents
set and binding the selection to a selectedDetent
state variable.
Listening for Position Changes
To respond to changes in the sheet position, I use the onChange
modifier to update the UI based on the selected detent. I ran into a tricky problem where the selectedDetent
binding updated and refreshed the ControlPanel
view, it interfered with the actual detent change. This led to a situation where showDetailedControls
would update, but the sheet position would not, resulting in a mismatched view state. To fix this, I implemented a small delay:
This delay gives the sheet time to complete its position change before updating showDetailedControls
. By running this in a separate task and updating the UI on the main thread, I ensure smooth transitions without blocking other UI updates.
Adding Smooth Animations
To make the UI changes feel smooth and polished, let's add some animations. I directly apply the animation modifier to the view:
Updating the Control Panel For Disclosure Groups
In the ControlPanel
view, I added a constant for showDetailedControls
:
This allows the ControlPanel
to update itself to changes in the sheet position to show the detailed controls. Also, I encountered a small bug where I wanted the disclosure group to close when the sheet was in its peek state:
This code closes the templates disclosure group whenever the detailed controls are hidden!
Finally, here is how it looks:
Moving Forward
The discloure group closing is still a bit glitchy but I have invested (or wasted) enough time that it is time to move forward with what I have.
I hope you find it as useful as I have! Feel free to adapt them to your own projects and let me know how it goes. Happy coding!