当键盘被解除时,如何在搜索栏中保持取消按钮?

时间:2014-06-05 23:53:15

标签: ios cocoa-touch ios7 uisearchbar

enter image description here enter image description here

我试图达到与Apple的联系人应用程序相同的效果(左侧截图)。即使键盘被解除,UISearchBar中的取消按钮也会启用。我的应用程序行为不同(右侧截图)。键盘解除后,取消按钮自动禁用。用户被迫点击取消按钮一次以启用它,然后再次点击实际触发解雇。这不是很好的用户体验。我如何始终像Apple的联系人应用程序一样启用取消按钮?

技术细节:

由于某些设计要求,我没有使用UISearchDisplayController。这只是UISearchBar我自己的自定义搜索控制器。取消按钮使用[self.searchBar showsCancelButton:YES animated:YES]显示。键盘被[self.searchBar resignFirstResponder]解雇。

11 个答案:

答案 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)