SwiftUI 2.0 List with children - how to make the tappable area of the disclosure button cover the whole list item
Here is a demo of approach (of course in your project you'd move expand/collapse state into view model)
struct DemoDisclosureGroups: View {
let items: [Bookmark] = [.example1, .example2, .example3]
@State private var flags: [Bool] = [false, false, false]
var body: some View {
List {
ForEach(Array(items.enumerated()), id: \.1.id) { i, group in
DisclosureGroup(isExpanded: $flags[i]) {
ForEach(group.items ?? []) { item in
Label(item.name, systemImage: item.icon)
}
} label: {
Label(group.name, systemImage: group.icon)
.contentShape(Rectangle())
.onTapGesture {
withAnimation {
self.flags[i].toggle()
}
}
}
}
}
}
}
struct Bookmark: Identifiable {
let id = UUID()
let name: String
let icon: String
var items: [Bookmark]?
// some example websites
static let apple = Bookmark(name: "Apple", icon: "1.circle")
static let bbc = Bookmark(name: "BBC", icon: "square.and.pencil")
static let swift = Bookmark(name: "Swift", icon: "bolt.fill")
static let twitter = Bookmark(name: "Twitter", icon: "mic")
// some example groups
static let example1 = Bookmark(name: "Favorites", icon: "star", items: [Bookmark.apple, Bookmark.bbc, Bookmark.swift, Bookmark.twitter])
static let example2 = Bookmark(name: "Recent", icon: "timer", items: [Bookmark.apple, Bookmark.bbc, Bookmark.swift, Bookmark.twitter])
static let example3 = Bookmark(name: "Recommended", icon: "hand.thumbsup", items: [Bookmark.apple, Bookmark.bbc, Bookmark.swift, Bookmark.twitter])
}
SwiftUI (2.0) list with children crashes when trying to delete the last element
I seem to have been able to figure this out myself after a little more probing around. The out-of-range error occurred on this line:
DisclosureGroup(isExpanded: $goodies.users[i].isExpanded) {
(I was able to tell by replacing with .constant(true)
which stopped the crash.)
I was able to fix this by using a function that gives a custom binding given the index i
, which checks that the index is in range before accessing it:
func binding(for index: Int) -> Binding<Bool> {
Binding<Bool>(
get: {
if index > goodies.users.count - 1{
return false
}
return goodies.users[index].isExpanded
},
set: {
if index > goodies.users.count - 1 {
// do nothing
} else {
goodies.users[index].isExpanded = $0
}
}
)
}
Usage for the affected line:
DisclosureGroup(isExpanded: binding(for: i)) {
This fixes the crashing issue. It was a little hard to pinpoint before because I didn't realise the binding was accessed after the list item was removed. Hope this helps someone in the same position.
What are the requirements for a free expandable List in SwiftUI?
It is activated by sidebar list style (which in some conditions are considered as default), which you can use explicitly
List {
ForEach(userData.groupedBookings) { group in
Section(header: Text(group.key)) {
ForEach(group.items) { booking in
LessonRow(booking: booking)
}
}
}
}
.listStyle(SidebarListStyle())
as alternate you can use DisclosureGroup
explicitly to have disclosure behavior for sections, like in https://stackoverflow.com/a/63228810/12299030
Related Topics
Uitableviewcelldeleteconfirmationcontrol Issue
Split View Controller Must Be Root View Controller
Dynamically Increase Height of Uilabel & Tableview Cell
Uiwebview and Safari Comparison
Storing Uicolor Object in Core Data
Google Maps iOS Sdk: Custom Icons to Be Used as Markers
Changed +Load Method Order in Xcode 7
Hide Device Volume Hud View While Adjusitng Volume with Mpvolumeview Slider
"No Such Module 'Alamofire'" Xcode Won't Recognize Alamofire Framework
How to Calculate Actual Font Point Size in iOS 7 (Not the Bounding Rectangle)
Code Signing Error: Application Failed Codesign Verification
Sharing an Image Between Two Viewcontrollers During a Transition Animation
Setting "Applelanguages" Doesn't Change App Language
Download and Cache Images in Uitableviewcell
Singleton in iOS Objective C Doesn't Prevent More Than One Instance
Multiple Locations on Map (Using Mkmapitem and Clgeocoder)
Ios:Retrieve Rectangle Shaped Image from the Background Image