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

SwiftUI中如何给选中的搜索栏添加右侧按钮?若不可行则用UIKit实现

在SwiftUI中实现搜索栏聚焦时显示右侧按钮

一、SwiftUI原生实现方案

利用@FocusState监听搜索栏的焦点状态,结合toolbar条件渲染按钮,iOS 15+可用:

struct ContentView: View {
    @State private var searchText = ""
    @FocusState private var isSearchFocused: Bool // 跟踪搜索栏焦点
    
    var body: some View {
        // iOS 16+推荐用NavigationStack,兼容iOS15可替换为NavigationView
        NavigationStack {
            VStack {
                Text("Hello")
            }
            .searchable(text: $searchText)
            .focused($isSearchFocused) // 绑定焦点状态
            .navigationTitle("Hello")
            .toolbar {
                // 仅当搜索栏聚焦时显示按钮
                if isSearchFocused {
                    Button("完成") {
                        isSearchFocused = false // 点击后取消焦点
                        searchText = "" // 可选:清空搜索内容
                    }
                }
            }
        }
    }
}

这个方案直接用SwiftUI原生API实现,代码简洁,无需额外依赖。

二、UIKit集成方案(自定义度更高)

如果需要更灵活的自定义样式,或者兼容更低版本系统,可以通过UIViewRepresentable封装UISearchBar来实现:

1. 封装自定义搜索栏

struct CustomSearchBar: UIViewRepresentable {
    @Binding var text: String
    @Binding var isFocused: Bool
    var onButtonTap: () -> Void
    
    func makeUIView(context: Context) -> UISearchBar {
        let searchBar = UISearchBar()
        searchBar.delegate = context.coordinator
        searchBar.showsCancelButton = false // 隐藏默认取消按钮,使用自定义按钮
        return searchBar
    }
    
    func updateUIView(_ uiView: UISearchBar, context: Context) {
        uiView.text = text
        
        // 根据焦点状态添加/移除自定义按钮
        if isFocused {
            let completeButton = UIButton(type: .system)
            completeButton.setTitle("完成", for: .normal)
            completeButton.addTarget(context.coordinator, action: #selector(Coordinator.buttonTapped), for: .touchUpInside)
            
            uiView.addSubview(completeButton)
            // 布局按钮到搜索栏右侧
            completeButton.translatesAutoresizingMaskIntoConstraints = false
            NSLayoutConstraint.activate([
                completeButton.centerYAnchor.constraint(equalTo: uiView.centerYAnchor),
                completeButton.trailingAnchor.constraint(equalTo: uiView.trailingAnchor, constant: -16)
            ])
        } else {
            // 移除已添加的自定义按钮
            uiView.subviews.first(where: { $0 is UIButton })?.removeFromSuperview()
        }
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject, UISearchBarDelegate {
        let parent: CustomSearchBar
        
        init(_ parent: CustomSearchBar) {
            self.parent = parent
        }
        
        // 监听搜索栏开始编辑(聚焦)
        func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
            parent.isFocused = true
        }
        
        // 监听搜索栏结束编辑(失焦)
        func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
            parent.isFocused = false
        }
        
        // 同步搜索文本到SwiftUI状态
        func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
            parent.text = searchText
        }
        
        // 处理自定义按钮点击事件
        @objc func buttonTapped() {
            parent.onButtonTap()
            parent.isFocused = false
            parent.text = ""
        }
    }
}

2. 在SwiftUI视图中使用

struct ContentView: View {
    @State private var searchText = ""
    @State private var isSearchFocused = false
    
    var body: some View {
        NavigationStack {
            VStack {
                CustomSearchBar(
                    text: $searchText,
                    isFocused: $isSearchFocused,
                    onButtonTap: {
                        print("完成按钮被触发")
                        // 这里添加你的自定义逻辑
                    }
                )
                .padding()
                
                Text("Hello")
            }
            .navigationTitle("Hello")
        }
    }
}

这种方案支持完全自定义搜索栏的样式、按钮位置和交互逻辑,适配场景更广泛。

内容的提问来源于stack exchange,提问作者user19914183

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 00:25:31