SwiftUI:如何让搜索栏成为第一响应者?

8i9zcol2  于 2023-02-28  发布在  Swift
关注(0)|答案(2)|浏览(171)

我想让搜索栏成为第一响应者,只要视图出现。不幸的是,还没有@FocusState支持/其他调用来实现这一开箱即用。有没有其他方法来实现这一点?

struct SearchDemo: View {
    
    @State var searchString : String = ""
    
    var body: some View {
        NavigationView {
            List{
                Text("...")
            }
            .searchable(text: $searchString)
        }
    }
}
xqkwcwgp

xqkwcwgp1#

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 makeUIView(context: Context) -> UISearchBar {
        let searchBar = UISearchBar()
        searchBar.delegate = context.coordinator
        return searchBar
    }
    
    func updateUIView(_ searchBar: UISearchBar, context: Context) {
        searchBar.text = text
        searchBar.becomeFirstResponder()
    }
    
    func makeCoordinator() -> Coordinator {
        return Coordinator(text: $text)
    }
}

struct SearchDemo: View {
    
    @State var searchString : String = ""
    
    var body: some View {
        NavigationView {
            List{
                Text("...")
            }
            .overlay(SearchBar(text: $searchString).frame(width: 0, height: 0))
        }
    }
}

这种方法创建了一个名为SearchBar的自定义UIViewRepresentable,它 Package 了一个UISearchBar,并将其委托设置为一个Coordinator对象,该对象处理搜索栏文本的更改。在updateUIView中,我们设置了搜索栏的文本,并调用becomeFirstResponder来设置搜索栏的焦点。我们使用overlay修饰符将搜索栏覆盖在列表的顶部。注意我们将搜索栏的边框设置为width:0,高度:0使其不可见。
这两种方法都可以在视图出现时将焦点设置在搜索栏上。

7kqas0il

7kqas0il2#

有点笨拙,但你可以用Introspect来实现,虽然不是“视图一出现”,但这是我不用滚动自己的搜索控制器就能找到的最好的方法。

struct SearchView: View {
     @State var searchText: String = ""

     var body: some View {
          NavigationStack {
               SomeList()
                    .searchable(text: $searchText)
          }
          .introspectSearchController(customize: { controller in
               DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                    controller.searchBar.searchTextField.becomeFirstResponder()
               }
          })
     }
}

相关问题