SwiftUI如何实现点击整个DisclosureGroup Label行切换展开状态
问题原因与修复方案
1. 状态变更无法触发视图刷新
你定义的SectionBindingManager虽然遵守了ObservableObject协议,但存储展开状态的bindingValues属性没有添加@Published标记,值修改时不会向订阅的视图发送更新通知,因此看不到展开状态的变化。
2. 点击事件未正确操作绑定值
你在label的onTapGesture中直接调用isExpanded.toggle(),但当前作用域并没有定义isExpanded变量,需要先拿到当前菜系对应的展开状态绑定再进行操作。
修正代码
修正SectionBindingManager
class SectionBindingManager<T>: ObservableObject { // 新增@Published标记,状态变更时自动通知视图 @Published private var bindingValues: [UUID: T] = [:] func binding(for id: UUID, defaultValue: T) -> Binding<T> { Binding<T> { return self.bindingValues[id] ?? defaultValue } set: { value in self.bindingValues[id] = value } } }
这里去掉了不必要的bindings缓存,每次直接生成绑定即可,避免缓存导致的状态不同步问题。
修正列表部分代码
ForEach(cuisines, id: \.id) { cuisine in // 先拿到当前菜系对应的展开状态绑定 let isExpanded = sectionBinding(for: cuisine.id) DisclosureGroup(isExpanded: isExpanded) { ForEach(cuisine.sortedDishTypes(), id: \.id) { dishType in NavigationLink(destination: RecipeListView(cuisine: cuisine, selectedDishType: dishType)) { Text(dishType.name!) .padding(.leading, 20) } } } label: { HStack { Image(cuisine.icon ?? "North American") .resizable() .scaledToFit() .frame(width: 24, height: 24) Text(cuisine.name!) .font(.headline) .fontWeight(.semibold) .padding(.leading, 5) Spacer() } .contentShape(Rectangle()) .onTapGesture { withAnimation { // 操作绑定的包装值完成切换 isExpanded.wrappedValue.toggle() } } } }
内容的提问来源于stack exchange,提问作者forrest
相关产品推荐
相关产品推荐

