SwiftUI中如何阻止.searchable激活时隐藏导航栏及动画?
解决SwiftUI .searchable激活时隐藏导航标题和工具栏的动画问题
要阻止搜索栏激活时导航标题和工具栏的隐藏动画,有两种可行方案:
方案一:禁用系统默认动画
通过读取\.isSearching环境变量,强制保持导航标题和工具栏的显示状态,并禁用对应的动画触发:
- 在父视图中添加环境变量监听:
@Environment(\.isSearching) var isSearching
- 修改导航栏相关修饰符,添加动画禁用逻辑:
var body: some View { VStack { GroupInviteSearchContainerView(groupViewModel: groupViewModel, searchString: searchString) .searchable(text: $searchString, placement: .navigationBarDrawer(displayMode: .always)) .onSubmit(of: .search) { // 处理搜索提交 } } .navigationTitle("Invite Friends") .navigationBarTitleDisplayMode(.large) .toolbar { Button("\(groupViewModel.listSelection.count) Selected") { showSelectedSheet = true } } // 强制保持导航栏可见 .toolbar(.visible, for: .navigationBar) // 禁用搜索状态变化时的动画 .animation(nil, value: isSearching) .background(Color.primaryDark) }
这个方案通过animation(nil, value: isSearching)直接禁用了搜索状态切换时的所有动画,让导航标题和工具栏保持显示。
方案二:自定义搜索栏(完全控制行为)
如果系统默认的searchable无法满足需求,可以通过包装UIKit的UISearchController实现自定义搜索栏,完全控制是否隐藏导航栏元素:
- 创建自定义搜索栏视图:
struct CustomSearchBar: UIViewControllerRepresentable { @Binding var text: String let placeholder: String // 设置为false,阻止搜索时隐藏导航栏 let hidesNavigationBar = false func makeUIViewController(context: Context) -> UISearchController { let searchController = UISearchController(searchResultsController: nil) searchController.searchBar.placeholder = placeholder searchController.searchBar.text = text searchController.hidesNavigationBarDuringPresentation = hidesNavigationBar searchController.obscuresBackgroundDuringPresentation = false searchController.searchBar.delegate = context.coordinator return searchController } func updateUIViewController(_ uiViewController: UISearchController, context: Context) { uiViewController.searchBar.text = text } func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject, UISearchBarDelegate { let parent: CustomSearchBar init(_ parent: CustomSearchBar) { self.parent = parent } func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { parent.text = searchText } func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { searchBar.resignFirstResponder() // 处理搜索提交逻辑 } } }
- 在父视图中替换系统
searchable,使用自定义搜索栏构建导航栏:
var body: some View { VStack { GroupInviteSearchContainerView(groupViewModel: groupViewModel, searchString: searchString) } .toolbar { // 自定义导航标题 ToolbarItem(placement: .principal) { Text("Invite Friends") .font(.largeTitle) .fontWeight(.bold) } // 自定义右侧选中按钮 ToolbarItem(placement: .navigationBarTrailing) { Button("\(groupViewModel.listSelection.count) Selected") { showSelectedSheet = true } } // 添加自定义搜索栏 ToolbarItem(placement: .navigationBarTopLeading) { CustomSearchBar(text: $searchString, placeholder: "Search friends") } } .background(Color.primaryDark) }
这个方案通过完全自定义导航栏元素和搜索栏,彻底避免了系统默认的隐藏动画行为,实现完全可控的界面表现。
内容的提问来源于stack exchange,提问作者got2jam
相关产品推荐
相关产品推荐

