SwiftUI - 在列表中搜索 Header
SwiftUI - Search in List Header
我正在尝试使用 SwiftUI 重新创建每个人都知道的 UITableView:tableview header 中的一个简单搜索字段:
然而,SwiftUI 中的列表视图似乎甚至没有办法添加 header 或页脚。您可以将带有 TextField 的 header 设置为这样的部分:
@State private var searchQuery: String = ""
var body: some View {
List {
Section(header:
Group{
TextField($searchQuery, placeholder: Text("Search"))
.background(Color.white)
}) {
ListCell()
ListCell()
ListCell()
}
}
}
但是,我不确定这是否是最好的方法,因为:
- 当您向下滚动时,header 不会隐藏,正如您从 UITableView 中了解到的那样。
- SearchField 看起来不像我们熟悉和喜爱的搜索字段。
有人找到好的方法了吗?我不想依赖 UITableView。
Xcode 13 / SwiftUI 3
您现在可以使用 .searchable
使列表...可搜索!
struct ContentView: View {
@State private var searchQuery: String = ""
var body: some View {
NavigationView {
List {
ForEach(Array(1...100)
.map { "\([=10=])" }
.filter { searchQuery.isEmpty ? true : [=10=].contains(searchQuery) }
,id: \.self) { item in
Text(verbatim: item)
}
}
.navigationTitle("Fancy Numbers")
.searchable(text: $searchQuery)
}
}
}
搜索栏似乎只有在 List
嵌入 NavigationView
时才会出现。
Xcode 12、SwiftUI 1/2
您可以将 UISearchBar
移植到 SwiftUI。
(有关此内容的更多信息,请参阅精彩的 WWDC 2019 演讲 - Integrating SwiftUI)
struct SearchBar: UIViewRepresentable {
@Binding var text: String
class Coordinator: NSObject, UISearchBarDelegate {
@Binding var text: String
init(text: Binding<String>) {
_text = text
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
text = searchText
}
}
func makeCoordinator() -> Coordinator {
return Coordinator(text: $text)
}
func makeUIView(context: UIViewRepresentableContext<SearchBar>) -> UISearchBar {
let searchBar = UISearchBar(frame: .zero)
searchBar.delegate = context.coordinator
return searchBar
}
func updateUIView(_ uiView: UISearchBar,
context: UIViewRepresentableContext<SearchBar>) {
uiView.text = text
}
}
并像这样使用它:
struct ContentView: View {
@State private var searchQuery: String = ""
var body: some View {
List {
Section(header: SearchBar(text: self.$searchQuery)) {
ForEach(Array(1...100).filter {
self.searchQuery.isEmpty ?
true :
"\([=12=])".contains(self.searchQuery)
}, id: \.self) { item in
Text("\(item)")
}
}
}
}
}
这是正确的搜索栏,但它不会隐藏 - 我相信我们将来可以通过 SwiftUI 做到这一点 API。
看起来像这样:
也许这里是一个起点。考虑使用 ZStack
为滚动视图的滚动消失效果。
struct ContentView: View {
@State var search: String
var body: some View {
NavigationView {
VStack(alignment: .center, spacing: 0) {
HStack {
Image(systemName: "magnifyingglass")
.padding(.leading, CGFloat(10.0))
TextField("Search", text: $search, onEditingChanged: { active in
print("Editing changed: \(active)")
}, onCommit: {
print("Commited: \(self.search)")
})
.padding(.vertical, CGFloat(4.0))
.padding(.trailing, CGFloat(10.0))
}
.overlay(
RoundedRectangle(cornerRadius: 5.0)
.stroke(Color.secondary, lineWidth: 1.0)
)
.padding()
List {
ForEach(0...100, id: \.self) { e in
Text("Item \(e)")
}
}
}
.navigationBarTitle(title(for: self.search))
}
}
private func title(for value: String?) -> String {
guard let value = value, value.count > 0 else {
return "No search"
}
return #"Searching for "\#(value)""#
}
}
我使用 SwiftUI 实现了我的国家/地区选择器项目 Columbus
。我实施了一个自定义发布者 CountryListViewModel
并将其与文本字段相关联。这样我就可以键入、搜索数据源、过滤结果/去抖动并在所有操作完成后更新 table 视图。效果很好
https://github.com/Blackjacx/Columbus/tree/swift-ui/Source/Classes
2021 — Xcode 13 / SwiftUI 3
原生 SwiftUI 解决方案:
List {
ForEach(0..<5) {
index in
Text("item \(index)")
}
}
}
.searchable(text: .constant("search_value")) // should be a Binding
我正在尝试使用 SwiftUI 重新创建每个人都知道的 UITableView:tableview header 中的一个简单搜索字段:
然而,SwiftUI 中的列表视图似乎甚至没有办法添加 header 或页脚。您可以将带有 TextField 的 header 设置为这样的部分:
@State private var searchQuery: String = ""
var body: some View {
List {
Section(header:
Group{
TextField($searchQuery, placeholder: Text("Search"))
.background(Color.white)
}) {
ListCell()
ListCell()
ListCell()
}
}
}
但是,我不确定这是否是最好的方法,因为:
- 当您向下滚动时,header 不会隐藏,正如您从 UITableView 中了解到的那样。
- SearchField 看起来不像我们熟悉和喜爱的搜索字段。
有人找到好的方法了吗?我不想依赖 UITableView。
Xcode 13 / SwiftUI 3
您现在可以使用 .searchable
使列表...可搜索!
struct ContentView: View {
@State private var searchQuery: String = ""
var body: some View {
NavigationView {
List {
ForEach(Array(1...100)
.map { "\([=10=])" }
.filter { searchQuery.isEmpty ? true : [=10=].contains(searchQuery) }
,id: \.self) { item in
Text(verbatim: item)
}
}
.navigationTitle("Fancy Numbers")
.searchable(text: $searchQuery)
}
}
}
搜索栏似乎只有在 List
嵌入 NavigationView
时才会出现。
Xcode 12、SwiftUI 1/2
您可以将 UISearchBar
移植到 SwiftUI。
(有关此内容的更多信息,请参阅精彩的 WWDC 2019 演讲 - Integrating SwiftUI)
struct SearchBar: UIViewRepresentable {
@Binding var text: String
class Coordinator: NSObject, UISearchBarDelegate {
@Binding var text: String
init(text: Binding<String>) {
_text = text
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
text = searchText
}
}
func makeCoordinator() -> Coordinator {
return Coordinator(text: $text)
}
func makeUIView(context: UIViewRepresentableContext<SearchBar>) -> UISearchBar {
let searchBar = UISearchBar(frame: .zero)
searchBar.delegate = context.coordinator
return searchBar
}
func updateUIView(_ uiView: UISearchBar,
context: UIViewRepresentableContext<SearchBar>) {
uiView.text = text
}
}
并像这样使用它:
struct ContentView: View {
@State private var searchQuery: String = ""
var body: some View {
List {
Section(header: SearchBar(text: self.$searchQuery)) {
ForEach(Array(1...100).filter {
self.searchQuery.isEmpty ?
true :
"\([=12=])".contains(self.searchQuery)
}, id: \.self) { item in
Text("\(item)")
}
}
}
}
}
这是正确的搜索栏,但它不会隐藏 - 我相信我们将来可以通过 SwiftUI 做到这一点 API。
看起来像这样:
也许这里是一个起点。考虑使用 ZStack
为滚动视图的滚动消失效果。
struct ContentView: View {
@State var search: String
var body: some View {
NavigationView {
VStack(alignment: .center, spacing: 0) {
HStack {
Image(systemName: "magnifyingglass")
.padding(.leading, CGFloat(10.0))
TextField("Search", text: $search, onEditingChanged: { active in
print("Editing changed: \(active)")
}, onCommit: {
print("Commited: \(self.search)")
})
.padding(.vertical, CGFloat(4.0))
.padding(.trailing, CGFloat(10.0))
}
.overlay(
RoundedRectangle(cornerRadius: 5.0)
.stroke(Color.secondary, lineWidth: 1.0)
)
.padding()
List {
ForEach(0...100, id: \.self) { e in
Text("Item \(e)")
}
}
}
.navigationBarTitle(title(for: self.search))
}
}
private func title(for value: String?) -> String {
guard let value = value, value.count > 0 else {
return "No search"
}
return #"Searching for "\#(value)""#
}
}
我使用 SwiftUI 实现了我的国家/地区选择器项目 Columbus
。我实施了一个自定义发布者 CountryListViewModel
并将其与文本字段相关联。这样我就可以键入、搜索数据源、过滤结果/去抖动并在所有操作完成后更新 table 视图。效果很好
https://github.com/Blackjacx/Columbus/tree/swift-ui/Source/Classes
2021 — Xcode 13 / SwiftUI 3
原生 SwiftUI 解决方案:
List {
ForEach(0..<5) {
index in
Text("item \(index)")
}
}
}
.searchable(text: .constant("search_value")) // should be a Binding