swiftui - 如何使用 SwiftUI 显示搜索栏

标签 swiftui

新的 SwiftUI 框架似乎没有提供内置的搜索栏组件。我应该使用 UISearchController 并以某种方式包装它,还是应该使用简单的文本字段并根据文本字段输入更新数据?
编辑:当前的解决方法是使用 TextField作为搜索栏。它运行良好,但没有搜索图标
enter image description here

import SwiftUI

struct Search : View {
  
  let array = ["John","Lena","Steve","Chris","Catalina"]
  
  @State private var searchText = ""
  
  var body: some View {
      NavigationView{
        List{
            TextField("Type your search",text: $searchText)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            
            ForEach(array.filter{$0.hasPrefix(searchText) || searchText == ""}, id:\.self){searchText in
                Text(searchText)
            }
        }
        .navigationBarTitle(Text("Search"))
      }
  }
}

struct Search_Previews : PreviewProvider {
  static var previews: some View {
    Search()
  }
}
更新到 Xcode 11.1

最佳答案

这是一个纯 swiftUI 版本,基于 Antoine Weber's回答他上面的问题以及我在 this blog 中发现的内容和 this gist .它包含

  • 清除按钮,
  • 取消按钮,
  • 在列表中拖动时退出键盘和
  • 选择搜索文本字段时隐藏导航 View 。

  • 在列表中拖动时退出键盘可以使用以下these answers UIApplication 窗口上的方法来实现.为了更容易处理,我在 UIApplication 上创建了一个扩展,并为此扩展创建了 View 修饰符,最后为 View 创建了一个扩展:

    extension UIApplication {
        func endEditing(_ force: Bool) {
            self.windows
                .filter{$0.isKeyWindow}
                .first?
                .endEditing(force)
        }
    }
    
    struct ResignKeyboardOnDragGesture: ViewModifier {
        var gesture = DragGesture().onChanged{_ in
            UIApplication.shared.endEditing(true)
        }
        func body(content: Content) -> some View {
            content.gesture(gesture)
        }
    }
    
    extension View {
        func resignKeyboardOnDragGesture() -> some View {
            return modifier(ResignKeyboardOnDragGesture())
        }
    }
    

    因此,退出键盘的最终修饰符只是一个必须放在列表中的修饰符,如下所示:

    List {
        ForEach(...) {
            //...
        }
    }
    .resignKeyboardOnDragGesture()
    

    带有示例名称列表的搜索栏的完整 swiftUI 项目代码如下。您可以将其粘贴到新的 swiftUI 项目的 ContentView.swift 中并使用它。

    
    import SwiftUI
    
    struct ContentView: View {
        let array = ["Peter", "Paul", "Mary", "Anna-Lena", "George", "John", "Greg", "Thomas", "Robert", "Bernie", "Mike", "Benno", "Hugo", "Miles", "Michael", "Mikel", "Tim", "Tom", "Lottie", "Lorrie", "Barbara"]
        @State private var searchText = ""
        @State private var showCancelButton: Bool = false
    
        var body: some View {
    
            NavigationView {
                VStack {
                    // Search view
                    HStack {
                        HStack {
                            Image(systemName: "magnifyingglass")
    
                            TextField("search", text: $searchText, onEditingChanged: { isEditing in
                                self.showCancelButton = true
                            }, onCommit: {
                                print("onCommit")
                            }).foregroundColor(.primary)
    
                            Button(action: {
                                self.searchText = ""
                            }) {
                                Image(systemName: "xmark.circle.fill").opacity(searchText == "" ? 0 : 1)
                            }
                        }
                        .padding(EdgeInsets(top: 8, leading: 6, bottom: 8, trailing: 6))
                        .foregroundColor(.secondary)
                        .background(Color(.secondarySystemBackground))
                        .cornerRadius(10.0)
    
                        if showCancelButton  {
                            Button("Cancel") {
                                    UIApplication.shared.endEditing(true) // this must be placed before the other commands here
                                    self.searchText = ""
                                    self.showCancelButton = false
                            }
                            .foregroundColor(Color(.systemBlue))
                        }
                    }
                    .padding(.horizontal)
                    .navigationBarHidden(showCancelButton) // .animation(.default) // animation does not work properly
    
                    List {
                        // Filtered list of names
                        ForEach(array.filter{$0.hasPrefix(searchText) || searchText == ""}, id:\.self) {
                            searchText in Text(searchText)
                        }
                    }
                    .navigationBarTitle(Text("Search"))
                    .resignKeyboardOnDragGesture()
                }
            }
        }
    }
    
    
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            Group {
               ContentView()
                  .environment(\.colorScheme, .light)
    
               ContentView()
                  .environment(\.colorScheme, .dark)
            }
        }
    }
    
    extension UIApplication {
        func endEditing(_ force: Bool) {
            self.windows
                .filter{$0.isKeyWindow}
                .first?
                .endEditing(force)
        }
    }
    
    struct ResignKeyboardOnDragGesture: ViewModifier {
        var gesture = DragGesture().onChanged{_ in
            UIApplication.shared.endEditing(true)
        }
        func body(content: Content) -> some View {
            content.gesture(gesture)
        }
    }
    
    extension View {
        func resignKeyboardOnDragGesture() -> some View {
            return modifier(ResignKeyboardOnDragGesture())
        }
    }
    

    搜索栏的最终结果,最初显示时如下所示

    enter image description here

    当搜索栏像这样编辑时:

    enter image description here

    在行动:

    enter image description here

    关于swiftui - 如何使用 SwiftUI 显示搜索栏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56490963/

    相关文章:

    ios - SwiftUi 多个foreach

    firebase - SwiftUI:从 DetailView 更新 Firestore

    swiftui - iOS 15 中的导航 + Tabview + Sheet 损坏

    ios - 快速组合 : Unable to infer complex closure return type error

    ios - 选择后 SwiftUI 选择器动画错误

    SwiftUI:如何使用非模拟器支持的框架和 PreviewProvider?

    ios - 将按钮添加到导航栏标题 Swiftui

    swiftui - UIKit > SwiftUI > UIKit 时未显示导航栏项目

    animation - 简单的过渡动画在 SwiftUI 中不起作用

    ios - 无法解决 "Type of expression is ambiguous without more context"错误。有人可以检查我的代码吗?