How do you keep the cancel button in the search ba

2020-06-01 05:27发布

enter image description here enter image description here

I'm trying to achieve the same effect as Apple's Contacts app (left screenshot). The cancel button in UISearchBar is enabled even when the keyboard is dismissed. My app behaves differently (right screenshot). The cancel button automatically becomes disabled when the keyboard is dismissed. The user is forced to tap the cancel button one time to enable it and then another time to actually trigger the dismissal. This is not good user experience. How would I always keep the cancel button enabled like Apple's Contacts app?

Technical Details:

I'm not using UISearchDisplayController due to some design requirements. This is just a UISearchBar with my own custom search controller. The cancel button is shown using [self.searchBar showsCancelButton:YES animated:YES]. The keyboard is dismissed using [self.searchBar resignFirstResponder].

11条回答
孤傲高冷的网名
2楼-- · 2020-06-01 05:36

Here's a recursive solution that is working for me.

func enableButtons(_ view:UIView) { for subView in view.subviews { enableButtons(subView) } if let buttonView = view as? UIButton { buttonView.isEnabled = true } }

查看更多
姐就是有狂的资本
3楼-- · 2020-06-01 05:36

This Worked For me

// ViewdidLoad()
SearchBar.enableCancelButton(in: ParentViewOfSearchBar)
查看更多
放我归山
4楼-- · 2020-06-01 05:37

This is what worked for me to handle any dismissal such as searchBar.resignFirstResponder(), view.endEditing(false), interactive swipe to dismiss, presenting a view controller, etc.

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
    }

}

Making sure to set searchBar.delegate = self.

查看更多
SAY GOODBYE
5楼-- · 2020-06-01 05:44

Try this simple solution, works perfect for me

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)
        }
    }
}
查看更多
闹够了就滚
6楼-- · 2020-06-01 05:46

You can use the runtime API to access the cancel button.

UIButton *btnCancel = [self.searchBar valueForKey:@"_cancelButton"];
[btnCancel setEnabled:YES];

As far as your question is concerned, there is no way you can enable the cancel button when the keyboard is dismissed, like there is no callback as such.

查看更多
别忘想泡老子
7楼-- · 2020-06-01 05:48

Implement the below searchBarShouldEndEditing delegate method in your code. Hope it will helpful.

(BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar 
{
    [[searchBar valueForKey:@"_cancelButton"] setEnabled:YES];
    return YES;
}
查看更多
登录 后发表回答