You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中如何阻止.searchable激活时隐藏导航栏及动画?

解决SwiftUI .searchable激活时隐藏导航标题和工具栏的动画问题

要阻止搜索栏激活时导航标题和工具栏的隐藏动画,有两种可行方案:

方案一:禁用系统默认动画

通过读取\.isSearching环境变量,强制保持导航标题和工具栏的显示状态,并禁用对应的动画触发:

  1. 在父视图中添加环境变量监听:
@Environment(\.isSearching) var isSearching
  1. 修改导航栏相关修饰符,添加动画禁用逻辑:
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实现自定义搜索栏,完全控制是否隐藏导航栏元素:

  1. 创建自定义搜索栏视图:
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()
            // 处理搜索提交逻辑
        }
    }
}
  1. 在父视图中替换系统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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 20:30:27