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
相关产品推荐
相关产品推荐

