我试图达到与Apple的联系人应用程序相同的效果(左侧截图)。即使键盘被解除,UISearchBar中的取消按钮也会启用。我的应用程序行为不同(右侧截图)。键盘解除后,取消按钮自动禁用。用户被迫点击取消按钮一次以启用它,然后再次点击实际触发解雇。这不是很好的用户体验。我如何始终像Apple的联系人应用程序一样启用取消按钮?
技术细节:
由于某些设计要求,我没有使用UISearchDisplayController
。这只是UISearchBar
我自己的自定义搜索控制器。取消按钮使用[self.searchBar showsCancelButton:YES animated:YES]
显示。键盘被[self.searchBar resignFirstResponder]
解雇。
答案 0 :(得分:11)
致电[self.searchBar resignFirstResponder]
将取消取消按钮。因此,您应该在调用后更新取消按钮以启用它。
<强>目标C 强>
[searchBar resignFirstResponder];
UIButton *cancelButton = (UIButton *)[searchBar valueForKey:@"cancelButton"];
[cancelButton setEnabled:YES];
<强>夫特强>
searchBar.resignFirstResponder()
if let cancelButton = searchBar.value(forKey: "cancelButton") as? UIButton
cancelButton.isEnabled = true
}
根据我的经验,view.endEditing(true)
就是问题所在。因为如果视图中有一个UITextField,它也被称为.resignFirstResponder
,它包含在UISearchBar中。
https://developer.apple.com/reference/uikit/uiview/1619630-endediting
答案 1 :(得分:5)
您可以使用运行时API访问取消按钮。
UIButton *btnCancel = [self.searchBar valueForKey:@"_cancelButton"];
[btnCancel setEnabled:YES];
就您的问题而言,当键盘被解除时,您无法启用取消按钮,就像没有回调一样。
答案 2 :(得分:3)
从iOS 7开始,UISearchBar的所有子视图都更深一层。这应该有效:
for (UIView *subView in searchBar.subviews) {
for (UIView *secondLevelSubview in subView.subviews) {
if ([view isKindOfClass:[UIButton class]]) {
[(UIButton *)view setEnabled:YES];
}
}
仍然很容易在下一个iOS版本中破解。
答案 3 :(得分:3)
对于Swift 4.0
if let cancelButton : UIButton = searchBar.value(forKey: "_cancelButton") as? UIButton{
cancelButton.isEnabled = true
}
答案 4 :(得分:1)
你可以这样做:
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
[self enableCancelButton];
}
- (void)enableCancelButton {
for (UIView *view in _seachBar.subviews) {
if ([view isKindOfClass:[UIButton class]]) {
[(UIButton *)view setEnabled:YES];
}
}
}
但是 这是一种非常糟糕的方法,而且我相当肯定它一般不受苹果公司的反对,可能导致应用程序出现问题被拒绝。据我所知,似乎没有任何其他方式可以做你想做的事情。
答案 5 :(得分:1)
这是一个适合我的递归解决方案。
func enableButtons(_ view:UIView) {
for subView in view.subviews {
enableButtons(subView)
}
if let buttonView = view as? UIButton {
buttonView.isEnabled = true
}
}
答案 6 :(得分:1)
尝试这个简单的解决方案,对我来说很完美
extension UISearchBar {
func enableCancelButton(in view: UIView) {
view.subviews.forEach {
enableCancelButton(in: $0)
}
if let cancelButton = view as? UIButton {
cancelButton.isEnabled = true
cancelButton.isUserInteractionEnabled = true
}
}
}
extension ViewController: UISearchBarDelegate {
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
DispatchQueue.main.async {
searchBar.enableCancelButton(in: searchBar)
}
}
}
答案 7 :(得分:1)
这对我来说很适合处理任何解雇,例如searchBar.resignFirstResponder()
,view.endEditing(false)
,交互式滑动以解雇,显示视图控制器等。
extension ViewController: UISearchBarDelegate {
func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool {
//cancel button becomes disabled when search bar isn't first responder, force it back enabled
DispatchQueue.main.async {
if let cancelButton = searchBar.value(forKey: "cancelButton") as? UIButton {
cancelButton.isEnabled = true
}
}
return true
}
}
确保设置searchBar.delegate = self
。
答案 8 :(得分:0)
在代码中实现以下searchBarShouldEndEditing委托方法。希望它会有所帮助。
(BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar
{
[[searchBar valueForKey:@"_cancelButton"] setEnabled:YES];
return YES;
}
答案 9 :(得分:0)
这是一种简单的方法:
searchBar.resignFirstResponder()
(searchBar.value(forKey: "_cancelButton") as? UIButton)?.isEnabled = true
答案 10 :(得分:-1)
这对我有用
// ViewdidLoad()
SearchBar.enableCancelButton(in: ParentViewOfSearchBar)