Skip to content

Instantly share code, notes, and snippets.

@d4rkd3v1l
Last active January 31, 2024 02:24
Show Gist options
  • Save d4rkd3v1l/0321faf11a877adefea7c96d0b1f67d6 to your computer and use it in GitHub Desktop.
Save d4rkd3v1l/0321faf11a877adefea7c96d0b1f67d6 to your computer and use it in GitHub Desktop.
SwiftUI: DisclosureGroup "expansion handler" to only have one group expanded at a time, and automatically hiding the last one, when expanding a new one.
class ExpansionHandler<T: Equatable>: ObservableObject {
@Published private (set) var expandedItem: T?
func isExpanded(_ item: T) -> Binding<Bool> {
return Binding(
get: { item == self.expandedItem },
set: { self.expandedItem = $0 == true ? item : nil }
)
}
func toggleExpanded(for item: T) {
self.expandedItem = self.expandedItem == item ? nil : item
}
}
// Usage:
// Some `Equatable` type, can also use basic types like `String` or `Date`.
enum ExpandableSection: Equatable {
case section
case anotherSection
}
@StateObject private var expansionHandler = ExpansionHandler<ExpandableSection>()
DisclosureGroup(
isExpanded: self.expansionHandler.isExpanded(.section),
content: {
// ...
},
label: {
// ...
}
)
.contentShape(Rectangle()) // Usability feature to have the whole item tappable, and not just the label/disclosure indicator
.onTapGesture {
withAnimation { self.expansionHandler.toggleExpanded(for: .section) }
}
@IniongunIsaac
Copy link

Works as a charm! Kudos!!! 🚀🚀🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment