SwiftUI中如何在搜索栏获焦时展开折叠的List Section
解决方案
修改代码,通过监听搜索状态的变化同步更新Section的展开状态,实现搜索栏激活时自动展开所有Section:
struct ContentView: View { @State private var searchText: String = "" @State private var showingSection = true // 可选:保存搜索前的Section展开状态,用于搜索结束后恢复原状态 @State private var preSearchSectionState = true @Environment(\.isSearching) private var isSearching var body: some View { NavigationStack { List { Section( isExpanded: $showingSection, content: { Text("One") Text("Two") Text("Three") }, header: { Text("Section") } ) } .listStyle(.sidebar) .searchable(text: $searchText) // 监听搜索状态变化 .onChange(of: isSearching) { newValue in if newValue { // 搜索栏激活时,保存当前状态并展开Section preSearchSectionState = showingSection showingSection = true } else { // 可选:搜索结束后恢复之前的展开状态 showingSection = preSearchSectionState } } } } }
原理说明
环境变量的只读限制:
@Environment(\.isSearching)是SwiftUI提供的只读环境变量,仅能用于读取当前是否处于搜索状态,无法通过$获取双向绑定(Binding<Bool>)。而Section的isExpanded参数要求传入可双向修改的绑定,所以直接写$isSearching会报错。状态中转逻辑:
- 我们使用自定义的
@State private var showingSection作为Section展开状态的数据源,它可以提供合法的Binding<Bool>(即$showingSection)。 - 通过
.onChange(of: isSearching)监听搜索状态变化:- 当
isSearching变为true(搜索栏获得焦点),先保存当前Section的展开状态(可选操作),再强制将showingSection设为true,展开所有Section。 - 当
isSearching变为false(搜索栏失去焦点),可选择恢复到搜索前的展开状态,提升用户体验。
- 当
- 我们使用自定义的
多Section扩展:如果List包含多个可折叠Section,只需给每个Section对应一个
@State变量,在onChange回调中统一将这些变量设为true即可。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

