44 votes

UISearchbar clearButton force l'apparition du clavier

J'ai une barre de recherche UISearchBar qui agit comme un filtre en direct pour une vue de tableau. Lorsque l'on quitte le clavier via endEditing :, le texte de la requête et le bouton circulaire gris "clear" restent. À partir de là, si je touche le bouton gris "effacer", le clavier réapparaît et le texte est effacé.

Comment puis-je éviter cela ? Si le clavier n'est pas actuellement ouvert, je veux que ce bouton efface le texte sans rouvrir le clavier.

Il y a une méthode de protocole qui est appelée lorsque je touche le bouton d'effacement. Mais l'envoi à l'UISearchBar d'un message resignFirstResponder n'a aucun effet sur le clavier.

122voto

boliva Points 2588

Il s'agit d'une vieille question. Je viens de rencontrer le même problème et j'ai réussi à le résoudre de la manière suivante :

Lorsque le searchBar:textDidChange: de l'UISearchBarDelegate est appelée parce que l'utilisateur a appuyé sur le bouton "Effacer", la barre de recherche n'est pas encore devenue le premier intervenant. Nous pouvons donc en tirer parti afin de détecter si l'utilisateur avait en fait l'intention d'effacer la recherche et de ne pas mettre l'accent sur la barre de recherche et/ou de faire autre chose.

Pour en garder la trace, nous devons déclarer un fichier BOOL dans notre viewController qui est aussi le délégué de la barre de recherche (appelons-le shouldBeginEditing ) et lui donner une valeur initiale de YES (en supposant que notre classe viewController s'appelle SearchViewController) :

@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;
    }
}
...
@end

Plus tard, dans le UISearchBarDelegate, nous implémentons la fonction searchBar:textDidChange: y searchBarShouldBeginEditing: méthodes :

- (void)searchBar:(UISearchBar *)bar textDidChange:(NSString *)searchText {
    NSLog(@"searchBar:textDidChange: isFirstResponder: %i", [self.searchBar isFirstResponder]);
    if(![searchBar isFirstResponder]) {
        // user tapped the 'clear' button
        shouldBeginEditing = NO;
        // do whatever I want to happen when the user clears the search...
    }
}

- (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;
}

En gros, c'est tout.

Best

33voto

J'ai constaté que resignFirstResponder ne fonctionne pas lorsque textDidChange est appelé à partir d'une touche sur le "bouton d'effacement". Cependant, en utilisant performSelection: withObject: afterDelay: semble être une solution de rechange efficace :

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
    if ([searchText length] == 0) {
        [self performSelector:@selector(hideKeyboardWithSearchBar:) withObject:searchBar afterDelay:0];
    }
}

- (void)hideKeyboardWithSearchBar:(UISearchBar *)searchBar
{   
    [searchBar resignFirstResponder];   
}

8voto

benvolioT Points 3003

J'ai utilisé une combinaison de la réponse de @boliva et de celle de @radiospiel. responder à une autre question sur les SO :

@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

3voto

Peter Lapisu Points 3274

La meilleure solution, d'après mon expérience, est de mettre une UIButton (avec un arrière-plan clair et sans texte) au-dessus du bouton d'effacement du système, puis connectez un bouton d'effacement du système. IBAction

Avec autolayout, c'est plus que facile.

- (IBAction)searchCancelButtonPressed:(id)sender {

    [self.searchBar resignFirstResponder];
    self.searchBar.text = @"";

    // some of my stuff
    self.model.fastSearchText = nil;
    [self.model fetchData];
    [self reloadTableViewAnimated:NO];

}

0voto

Corey Floyd Points 16747

Dans votre méthode endEditing, pourquoi ne pas effacer la UISearchBar et là ? Puisque ce doit être là que vous resignez aussi le premier intervenant, c'est logique.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X