swiftui - SwiftUI 搜索栏与导航栏一致
问题描述
有没有人有工作的 Swiftui 代码,可以在导航栏中生成一个与后退按钮内联的搜索栏?好像它是一个工具栏项。
目前我有代码会在导航返回按钮下方生成一个搜索栏,但希望它像附图所示的那样排列(“hi”在哪里):
我正在使用在示例中找到的代码:
var body: some View {
let shopList = genShopList(receiptList: allReceipts)
VStack{
}
.navigationBarSearch(self.$searchInput)
}
public extension View {
public func navigationBarSearch(_ searchText: Binding<String>) -> some View {
return overlay(SearchBar(text: searchText)
.frame(width: 0, height: 0))
}
}
fileprivate struct SearchBar: UIViewControllerRepresentable {
@Binding
var text: String
init(text: Binding<String>) {
self._text = text
}
func makeUIViewController(context: Context) -> SearchBarWrapperController {
return SearchBarWrapperController()
}
func updateUIViewController(_ controller: SearchBarWrapperController, context: Context) {
controller.searchController = context.coordinator.searchController
}
func makeCoordinator() -> Coordinator {
return Coordinator(text: $text)
}
class Coordinator: NSObject, UISearchResultsUpdating {
@Binding
var text: String
let searchController: UISearchController
private var subscription: AnyCancellable?
init(text: Binding<String>) {
self._text = text
self.searchController = UISearchController(searchResultsController: nil)
super.init()
searchController.searchResultsUpdater = self
searchController.hidesNavigationBarDuringPresentation = true
searchController.obscuresBackgroundDuringPresentation = false
self.searchController.searchBar.text = self.text
self.subscription = self.text.publisher.sink { _ in
self.searchController.searchBar.text = self.text
}
}
deinit {
self.subscription?.cancel()
}
func updateSearchResults(for searchController: UISearchController) {
guard let text = searchController.searchBar.text else { return }
self.text = text
}
}
class SearchBarWrapperController: UIViewController {
var searchController: UISearchController? {
didSet {
self.parent?.navigationItem.searchController = searchController
}
}
override func viewWillAppear(_ animated: Bool) {
self.parent?.navigationItem.searchController = searchController
}
override func viewDidAppear(_ animated: Bool) {
self.parent?.navigationItem.searchController = searchController
}
}
}
如果有人对此问题有解决方案,将不胜感激!我知道在 IoS 15 中,他们推出了 .searchable,但也在寻找适用于早期版本的东西。
解决方案
.toolbar
您可以使用修饰符(iOS 14+)和带有位置的项目将任何控件放在您想要的.principal
位置,例如:
var body: some View {
VStack {
// rest of view
}
.toolbar {
ToolbarItem(placement: .principal) {
MySearchField(text: $searchText)
}
}
}
有几点需要注意:
主要位置会覆盖内联导航标题,无论是在设置时
.navigationBarTitleDisplayMode(.inline)
还是在您拥有大标题并向上滚动页面时。您的自定义视图可能会水平扩展太多,以至于后退按钮会丢失任何文本组件。在这里,我用一个
TextField
来说明这一点:
您可以通过为 分配最大宽度来缓解这种情况.frame(maxWidth:)
,但至少需要注意这一点。
推荐阅读
- peewee - Peewee 连接查询无法获取数据
- python-cryptography - 密码学重复密钥异或密码
- dart - 如何在私有变量上使用飞镖类属性
- node.js - Passport Google 策略重定向 500 状态码
- api - CORS Google script API Error call google script webapp API url by script tag Src
- c - 如何使用 c++ 在 linux shell 中查看当前路径?
- authentication - 将 6.4 eap 迁移到 7.2 eap 时,Jboss Authentication principalsQuery 不起作用
- sql - 如何使用不相等的列和行连接 2 个 SQL 查询
- vba - 取平方根时无效的过程调用或参数(0.5 次方)
- jquery - BootStrap 模态弹出窗口未使用 JQuery 打开