Отключение клавиатуры от UISearchBar при нажатии кнопки X
Я использую UISearchBar (но не SearchDisplayController, который обычно используется в сочетании), и я хотел бы убрать клавиатуру, когда вы нажимаете кнопку "X".
Я следовал предложению TomSwift о вызове, когда "X" прослушивается, и это отлично работает. Но отставка первого ответчика из текстового поля, а также вызов в экземпляре UISearchBar, как с resignFirstResponder
, не заставят клавиатуру уйти.
Есть ли способ избавиться от клавиатуры, когда пользователь нажал кнопку X?
Вот что я сделал, чтобы получить сообщение "Очистить":
- (void)viewDidLoad:
{
for (UIView* v in searchBar.subviews)
{
if ( [v isKindOfClass: [UITextField class]] )
{
UITextField *tf = (UITextField *)v;
tf.delegate = self;
break;
}
}
}
Затем у меня есть моя настройка класса для реализации как UISearchBarDelegate, так и UITextFieldDelegate.
Наличие класса в качестве делегата текстового поля позволяет мне получить этот вызов:
- (BOOL)textFieldShouldClear:(UITextField *)textField
{
[textField resignFirstResponder];
[self.searchBar resignFirstResponder];
return YES;
}
Я пробовал все, что мог придумать. Последнее, что я пытаюсь найти способ вывести "searchBarCancelButtonClicked", который UISearchDelegate будет вызывать в моем классе Controller, но не уверен, как я мог это сделать, поскольку UISearchBar, похоже, не имеет прямых методов для вызывается с этим именем.
Ответы
Ответ 1
Update:
Ну, это полный хак, но я смог заставить его работать. В основном код вызывает обработчик для кнопки отмены. Чтобы заставить его работать, мне пришлось вызывать селектор с задержкой, и я не уверен, почему это должно было быть. Кроме того, мне пришлось написать аксессуар для кнопки отмены, как и для текстового поля.
Опять же, это полный взлом. Я не уверен, что сделаю это сам в приложении.
// this in the context of the search bar
- (UIButton*) cancelButton
{
for (UIView* v in self.subviews)
{
if ( [v isKindOfClass: [UIButton class]] )
return (UIButton*)v;
}
return nil;
}
// this is the textField delegate callback
- (BOOL)textFieldShouldClear:(UITextField *)textField
{
[textField resignFirstResponder];
UIButton* cb = _searchBar.cancelButton;
NSObject* target = [[cb allTargets] anyObject];
NSArray* actions = [cb actionsForTarget: target forControlEvent:UIControlEventTouchUpInside];
NSString* selectorName = [actions objectAtIndex:0];
SEL selector = NSSelectorFromString( selectorName );
[target performSelector: selector withObject: cb afterDelay: 0.1];
return YES;
}
Оригинальный ответ:
Как вы получаете четкую кнопку "X" для отображения в первую очередь? В моем тестовом примере я не вижу его отображения...
Попробуйте выполнить resignFirstResponder в searchBar, а не в текстовом поле.
Ответ 2
Томс ответ заставил меня думать. Если это так, что панель поиска еще не является первымResponder, когда пользователь нажимает кнопку очистки, мы можем просто подождать, пока она не появится, а затем у вас будет resignFirstResponder; т.е. вдоль линий:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
[self performFilteringBySearchText: searchText]; // or whatever
// The user clicked the [X] button or otherwise cleared the text.
if([searchText length] == 0) {
[searchBar performSelector: @selector(resignFirstResponder)
withObject: nil
afterDelay: 0.1];
}
}
Работает как шарм и менее хаки, чем Том ИМХО.
Ответ 3
Это работает:
[searchBar performSelector:@selector(resignFirstResponder) withObject:nil afterDelay:0.1];
Ответ 4
Обновлено для SWIFT 3:
Предположим, что пользователь ввел строку в поле поиска и щелкнул по x следующий код работает, чтобы скрыть клавиатуру при нажатии x
`
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String)
{
if searchBar.text == nil || searchBar.text == ""
{
searchBar.perform(#selector(self.resignFirstResponder), with: nil, afterDelay: 0.1)
}
}
`
Ответ 5
Вы можете resignFirstResponder нажать кнопку отмены как.
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
SearchBar.showsCancelButton =NO;
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
[SearchBar resignFirstResponder];
}
Ответ 6
Версия Swift 2:
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
// The user clicked the [X] button or otherwise cleared the text.
if (searchText.characters.count == 0) {
searchBar.performSelector("resignFirstResponder", withObject: nil, afterDelay: 0.1)
}
}
Ответ 7
Я нашел это в предыдущем вопросе:
Кнопка clearButton UISearchbar заставляет клавиатуру отображаться
Он должен делать именно то, что вы хотите сделать.
Ответ 8
Старайтесь избегать
- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar
в вашем коде мы можем решить этот
Ответ 9
Я использовал комбинацию ответа @radiospiel, а также ответ, который @Tozar связан с:
@interface SearchViewController : UIViewController <UISearchBarDelegate> {
// all of our ivar declarations go here...
BOOL shouldBeginEditing;
....
}
...
@end
@implementation SearchViewController
...
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
...
shouldBeginEditing = YES;
}
}
...
- (void) searchBar:(UISearchBar *)theSearchBar textDidChange:(NSString *)searchText {
// TODO - dynamically update the search results here, if we choose to do that.
if (![searchBar isFirstResponder]) {
// The user clicked the [X] button while the keyboard was hidden
shouldBeginEditing = NO;
}
else if ([searchText length] == 0) {
// The user clicked the [X] button or otherwise cleared the text.
[theSearchBar performSelector: @selector(resignFirstResponder)
withObject: nil
afterDelay: 0.1];
}
}
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)bar {
// reset the shouldBeginEditing BOOL ivar to YES, but first take its value and use it to return it from the method call
BOOL boolToReturn = shouldBeginEditing;
shouldBeginEditing = YES;
return boolToReturn;
}
@end
Ответ 10
Не следует ли изменять пользовательский интерфейс в основном потоке вместо использования performselector:WithObject:afterDelay:
?
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
if (searchText.length == 0) {
[searchBar performSelectorOnMainThread:@selector(resignFirstResponder) withObject:nil waitUntilDone:NO];
}
}
Ответ 11
РЕДАКТИРОВАТЬ: На самом деле ниже разбивается делегат, подключенный к UISearchBar. Просто подкласс UISearchBar и перезаписать метод UITextField Delegate.
===========================
Мне пришлось сделать это, чтобы получить доступ к UITextView
for (UIButton* v in [self.searchBar.subviews[0] subviews])
{
if ( [v isKindOfClass: [UITextField class]] )
{
UITextField *tf = (UITextField *)v;
tf.delegate = self;
break;
}
}
Ответ 12
Кредит Maxhs за оригинальный ответ:
Это быстрая версия 2.2:
Работайте как очарование для меня
if searchBar.text == "" {
dispatch_async(dispatch_get_main_queue(), {
self.searchBar.resignFirstResponder()
})
}
Ответ 13
Еще одна точка зрения для прозрачного потока текста (аналогичная @TomSwift, но более понятная для меня и менее сложная). Кроме того, мне нужно скрыть кнопку "Отмена" после выхода из панели поиска, реализовать прямой поиск (после каждого символа) и таблицу обложки перед тем, как пользователь выполнит поиск.
//self.searchHoverView can cover table view
//performSearchWithSearchBar: method for performing search
#pragma mark - UISearchBarDelegate
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
[searchBar setShowsCancelButton:YES animated:YES];
self.searchHoverView.hidden = NO;
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
if (searchText.length) {
[self performSearchWithSearchBar:searchBar];
} else {
UIButton *button;
for (UIView *subView in [searchBar subviews]) {
for (UIView *view in [subView subviews]) {
if ([view isKindOfClass:[UIButton class]]) {
button = (UIButton *)view;
break;
}
}
}
if (button) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[button sendActionsForControlEvents:UIControlEventTouchUpInside];
});
}
}
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
self.searchBar.text = nil;
[self.searchBar setShowsCancelButton:NO animated:YES];
[self.searchBar resignFirstResponder];
self.searchHoverView.hidden = YES;
}