如何在SwiftUI搜索栏中为SearchResultsButton添加Sheet弹窗功能?
实现搜索栏结果按钮点击弹出Sheet的方案
SwiftUI原生的searchable修饰符没有提供搜索结果按钮的点击回调接口,我们需要借助UIKit的UISearchBarDelegate来拦截按钮点击事件,进而触发Sheet弹窗。
步骤1:自定义搜索栏代理类
先创建一个遵循UISearchBarDelegate的类,用来监听搜索结果按钮的点击动作:
import SwiftUI class CustomSearchBarDelegate: NSObject, UISearchBarDelegate { var resultsButtonAction: (() -> Void)? func searchBarResultsListButtonClicked(_ searchBar: UISearchBar) { resultsButtonAction?() } }
步骤2:修改ContentView实现功能
更新你的ContentView,添加控制Sheet显示的状态变量,绑定代理的点击回调:
struct ContentView: View { @State private var searchText = "" @State private var isResultsSheetPresented = false private let searchDelegate = CustomSearchBarDelegate() var body: some View { NavigationView { List { Text("Hello") Text("World") } .navigationTitle("Hello") .searchable(text: $searchText) .sheet(isPresented: $isResultsSheetPresented) { // 替换成你需要的Sheet内容视图 VStack(spacing: 20) { Text("搜索结果页面") .font(.title) Text("这里展示你的搜索结果") } .padding() } .onAppear { // 显示搜索结果按钮 UISearchBar.appearance().showsSearchResultsButton = true // 递归查找视图层级中的UISearchBar并设置代理 if let searchBar = findSearchBar(in: UIApplication.shared.windows.first?.rootViewController?.view) { searchBar.delegate = searchDelegate } // 绑定按钮点击事件 searchDelegate.resultsButtonAction = { isResultsSheetPresented = true } } } } // 递归查找视图中的UISearchBar实例 private func findSearchBar(in view: UIView?) -> UISearchBar? { guard let view = view else { return nil } if let searchBar = view as? UISearchBar { return searchBar } for subview in view.subviews { if let found = findSearchBar(in: subview) { return found } } return nil } }
补充说明
findSearchBar方法通过递归遍历视图层级查找UISearchBar,比直接取子视图的方式更可靠,适配复杂视图结构。- Sheet中的内容可以完全自定义,比如添加搜索结果列表、筛选控件等,替换示例中的
VStack即可。 - 若使用iOS 16+,可将
NavigationView替换为NavigationStack,代码逻辑保持不变。
内容的提问来源于stack exchange,提问作者user19914183
相关产品推荐
相关产品推荐

