iOS - 如何在点击 UIView 的任意位置时从 navigationItem.searchController 关闭键盘?
iOS - How to dismiss keyboard from the navigationItem.searchController when tap anywhere on the UIView?
我已经实现了新的 SearchController
及其 searchBar
和 searchResultsController
。
以下是我的实现方式:
结果视图控制器:
lazy var resultViewController: SearchResultViewController = {
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let searchResultViewController = storyboard.instantiateViewController(withIdentifier: "SearchResultViewController") as! SearchResultViewController
searchResultViewController.delegate = self
return searchResultViewController
}()
这是搜索控制器:
lazy var searchController: UISearchController = {
let searchController = UISearchController(searchResultsController: resultViewController)
searchController.searchBar.delegate = self
searchController.obscuresBackgroundDuringPresentation = true
searchController.searchResultsUpdater = self
searchController.searchBar.placeholder = "Search.city.label".localizable()
searchController.searchBar.tintColor = UIColor.white
searchController.searchBar.barTintColor = UIColor.white
UITextField.appearance(whenContainedInInstancesOf: [type(of: searchController.searchBar)]).tintColor = UIColor(red:0.00, green:0.47, blue:0.78, alpha:1.0)
if let textfield = searchController.searchBar.value(forKey: "searchField") as? UITextField {
if let backgroundview = textfield.subviews.first {
// Background color
backgroundview.backgroundColor = UIColor.white
// Rounded corner
backgroundview.layer.cornerRadius = 10;
backgroundview.clipsToBounds = true;
}
}
definesPresentationContext = true
return searchController
}()
在我的 viewWillAppear
中,我设置了 navigationItem.searchController :
self.searchController.isActive = true
if #available(iOS 11.0, *) {
self.navigationItem.searchController = searchController
self.navigationItem.hidesSearchBarWhenScrolling = true
} else {
// Fallback on earlier versions
}
我已经能够处理 cancelButtonClicked :
extension HomeViewController: UISearchBarDelegate {
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.endEditing(true)
self.searchController.isActive = false
}
}
这是在做 "cancel" 动画,在 searchBar/searchController 上隐藏键盘 + 非活动状态。同时点击取消按钮 1 次。
但是当用户点击视图上的任意位置时,我无法实现这一点。
我尝试使用点击手势,但它需要我点击 2 次才能实现相同的行为。
注意:
我的 UIViewController 中有一个 UICollectionView,它占据了 UIView 中的所有位置。
这是我试过的方法:
override func viewDidLoad() {
super.viewDidLoad()
handleTapAnywhereToRemoveKeyboard()
}
func handleTapAnywhereToRemoveKeyboard() {
let singleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.singleTap(sender:)))
//singleTapGestureRecognizer.numberOfTapsRequired = 1
singleTapGestureRecognizer.cancelsTouchesInView = false
self.view.addGestureRecognizer(singleTapGestureRecognizer)
}
@objc func singleTap(sender: UITapGestureRecognizer) {
self.searchController.isActive = false
self.searchController.searchBar.resignFirstResponder()
self.searchController.searchBar.endEditing(true)
}
编辑:
我在想,也许是因为我的 searchBar 和 searchController 不在 UIViewController 的视图层次结构中,而是在 NavigationController 的视图层次结构中。
所以我也试过 :
navigationController?.view.endEditing(true)
然后我在想,也许是因为我的 UICollectionView 中的 UIScrollView 正在捕捉水龙头。
所以我尝试 link 在 UICollectionView 而不是 UIView 上点击手势,但没有成功。
请创建 UIViewController
以关闭键盘整个应用程序。
extension UIViewController {
func hideKeyboardWhenTappedAround() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
@objc func dismissKeyboard() {
view.endEditing(true)
}
}
在您的 UIViewController
文件中使用上面的代码,如下所示。
override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardWhenTappedAround()
}
更新:
您还可以使用以下代码从任何 class.
中关闭键盘
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
尝试 Dimple Desai 的解决方案,但将手势识别器添加到 TableView 或 CollectionView 或位于 UIView 之上的任何内容。然后它应该工作。
override func viewDidLoad(){
let tapView = UITapGestureRecognizer(target: self, action: #selector(self.hideKeyboard))
self.view.addGestureRecognizer(tapView)
}
@objc func hideKeyboard(tap: UITapGestureRecognizer){
self.view.endEditing(true)
}
不需要按照上面的建议添加UITapGestureRecognizer
。 UIViewContoller
已经符合 UIResponder
接口(遗留于 Objective C),因此您可以像这样覆盖此方法:
extension UIViewController {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.window?.endEditing(true)
super.touchesEnded(touches, with: event)
}
}
我已经实现了新的 SearchController
及其 searchBar
和 searchResultsController
。
以下是我的实现方式:
结果视图控制器:
lazy var resultViewController: SearchResultViewController = {
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let searchResultViewController = storyboard.instantiateViewController(withIdentifier: "SearchResultViewController") as! SearchResultViewController
searchResultViewController.delegate = self
return searchResultViewController
}()
这是搜索控制器:
lazy var searchController: UISearchController = {
let searchController = UISearchController(searchResultsController: resultViewController)
searchController.searchBar.delegate = self
searchController.obscuresBackgroundDuringPresentation = true
searchController.searchResultsUpdater = self
searchController.searchBar.placeholder = "Search.city.label".localizable()
searchController.searchBar.tintColor = UIColor.white
searchController.searchBar.barTintColor = UIColor.white
UITextField.appearance(whenContainedInInstancesOf: [type(of: searchController.searchBar)]).tintColor = UIColor(red:0.00, green:0.47, blue:0.78, alpha:1.0)
if let textfield = searchController.searchBar.value(forKey: "searchField") as? UITextField {
if let backgroundview = textfield.subviews.first {
// Background color
backgroundview.backgroundColor = UIColor.white
// Rounded corner
backgroundview.layer.cornerRadius = 10;
backgroundview.clipsToBounds = true;
}
}
definesPresentationContext = true
return searchController
}()
在我的 viewWillAppear
中,我设置了 navigationItem.searchController :
self.searchController.isActive = true
if #available(iOS 11.0, *) {
self.navigationItem.searchController = searchController
self.navigationItem.hidesSearchBarWhenScrolling = true
} else {
// Fallback on earlier versions
}
我已经能够处理 cancelButtonClicked :
extension HomeViewController: UISearchBarDelegate {
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.endEditing(true)
self.searchController.isActive = false
}
}
这是在做 "cancel" 动画,在 searchBar/searchController 上隐藏键盘 + 非活动状态。同时点击取消按钮 1 次。
但是当用户点击视图上的任意位置时,我无法实现这一点。
我尝试使用点击手势,但它需要我点击 2 次才能实现相同的行为。
注意:
我的 UIViewController 中有一个 UICollectionView,它占据了 UIView 中的所有位置。
这是我试过的方法:
override func viewDidLoad() {
super.viewDidLoad()
handleTapAnywhereToRemoveKeyboard()
}
func handleTapAnywhereToRemoveKeyboard() {
let singleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.singleTap(sender:)))
//singleTapGestureRecognizer.numberOfTapsRequired = 1
singleTapGestureRecognizer.cancelsTouchesInView = false
self.view.addGestureRecognizer(singleTapGestureRecognizer)
}
@objc func singleTap(sender: UITapGestureRecognizer) {
self.searchController.isActive = false
self.searchController.searchBar.resignFirstResponder()
self.searchController.searchBar.endEditing(true)
}
编辑:
我在想,也许是因为我的 searchBar 和 searchController 不在 UIViewController 的视图层次结构中,而是在 NavigationController 的视图层次结构中。
所以我也试过 :
navigationController?.view.endEditing(true)
然后我在想,也许是因为我的 UICollectionView 中的 UIScrollView 正在捕捉水龙头。 所以我尝试 link 在 UICollectionView 而不是 UIView 上点击手势,但没有成功。
请创建 UIViewController
以关闭键盘整个应用程序。
extension UIViewController {
func hideKeyboardWhenTappedAround() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
@objc func dismissKeyboard() {
view.endEditing(true)
}
}
在您的 UIViewController
文件中使用上面的代码,如下所示。
override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardWhenTappedAround()
}
更新:
您还可以使用以下代码从任何 class.
中关闭键盘UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
尝试 Dimple Desai 的解决方案,但将手势识别器添加到 TableView 或 CollectionView 或位于 UIView 之上的任何内容。然后它应该工作。
override func viewDidLoad(){
let tapView = UITapGestureRecognizer(target: self, action: #selector(self.hideKeyboard))
self.view.addGestureRecognizer(tapView)
}
@objc func hideKeyboard(tap: UITapGestureRecognizer){
self.view.endEditing(true)
}
不需要按照上面的建议添加UITapGestureRecognizer
。 UIViewContoller
已经符合 UIResponder
接口(遗留于 Objective C),因此您可以像这样覆盖此方法:
extension UIViewController {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.window?.endEditing(true)
super.touchesEnded(touches, with: event)
}
}