SwiftUI Search Bar 与导航栏一致
SwiftUI Search Bar in line with navigation bar
是否有人拥有可在导航栏中生成与后退按钮内联的搜索栏的有效 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:)
分配最大宽度来缓解这种情况,但至少需要注意这一点。
是否有人拥有可在导航栏中生成与后退按钮内联的搜索栏的有效 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:)
分配最大宽度来缓解这种情况,但至少需要注意这一点。