web-dev-qa-db-fra.com

Puis-je accrocher dans le bouton Effacer de la barre de recherche?

J'ai une barre UISearchBar dans mon interface et je souhaite personnaliser le comportement du petit bouton clair qui apparaît dans la barre de recherche après la saisie de texte (c'est un petit cercle gris avec une croix, il apparaît à droite côté du champ de recherche).

Fondamentalement, je souhaite non seulement effacer le texte de la barre de recherche (qui est l'implémentation par défaut), mais également effacer d'autres éléments de mon interface, tout en appelant l'une de mes propres méthodes.

Je ne trouve rien dans la documentation de la classe UISearchBar ou du protocole UISearchBarDelegate - il ne semble pas que vous puissiez accéder directement à ce comportement.

La seule chose que j’ai constatée, c’est que la documentation explique que la méthode déléguée:

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText;

est appelé après que le bouton d'effacement est tapé.

Dans un premier temps, j'ai écrit un code dans cette méthode qui vérifiait la propriété textuelle de la barre de recherche. Si elle était vide, elle aurait été effacée et pour pouvoir effectuer toutes mes autres tâches.

Deux problèmes que cela cependant:

Premièrement, pour une raison quelconque, je ne peux pas comprendre, même si je dis à la barre de recherche de resignFirstResponder à la fin de ma méthode, quelque chose, quelque part, le réinitialise pour devenir First (répondeur). Vraiment énervant...

Deuxièmement, si l'utilisateur n'utilise pas le bouton Effacer et supprime simplement le texte de la barre à l'aide du bouton Supprimer du clavier, cette méthode est activée et les résultats de la recherche disparaissent. Pas bon.

Tout conseil ou indication dans la bonne direction serait génial!

Merci!

35
Jasarien

La réponse qui a été acceptée est incorrecte. Cela peut être fait, je viens de le comprendre et de le poster dans une autre question:

UISearchbar clearButton oblige le clavier à apparaître

Meilleur

11
boliva

Trouvé la meilleure solution pour ce problème :)

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

J'ai ce code dans mon application. La différence est que je ne supporte pas la 'recherche en direct', mais que je commence à chercher quand l'utilisateur appuie sur le bouton de recherche sur le clavier:

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
    if ([searchBar.text isEqualToString:@""]) {
        //Clear stuff here
    }
}
7
wvteijlingen

Swift version manipulant fermer le clavier sur le clic du bouton clair:

func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
    if searchText.characters.count == 0 {
        performSelector("hideKeyboardWithSearchBar:", withObject:searchBar, afterDelay:0)
    }
}

func hideKeyboardWithSearchBar(bar:UISearchBar) {
    bar.resignFirstResponder()
}
7
ergunkocak

Puisque cela vient en premier, et autant que je sache, la question n’a pas été suffisamment abordée, je pensais publier ma solution.

1) Vous devez obtenir une référence au champ textField dans la barre de recherche 2) Vous devez indiquer clairement que ce champ textField est dégagé lorsqu’il se déclenche.

C'est assez simple. Voici un moyen. 

a) Assurez-vous de faire de votre classe un car vous allez utiliser la méthode déléguée du champ textField dans le searchBar . b) Connectez également votre searchBar à une prise de votre classe. Je viens d'appeler le mien searchBar . C) de viewDidLoad, vous voulez obtenir le contenu de textField dans le searchBar. Je l'ai fait comme ça.

UITextField *textField = [self.searchBar valueForKey:@"_searchField"];
if (textField) {
    textField.delegate = self;
    textField.tag = 1000;
}

Remarquez, j'ai assigné une balise à textField afin de pouvoir la récupérer à nouveau et j'en ai fait un délégué textField. Vous auriez pu créer une propriété et assigner ce textField à cette propriété pour la récupérer plus tard, mais j'ai utilisé une balise.

A partir de là, il vous suffit d'appeler la méthode delegate:

-(BOOL)textFieldShouldClear:(UITextField *)textField {
if (textField.tag == 1000) {
    // do something
    return YES;
}
return NO;

}

C'est tout. Puisque vous vous référez à une valeur privéeForKey, je ne peux pas garantir que cela ne vous causera pas de problèmes.

1
smileBot

Vous pouvez essayer ceci:

- (void)viewDidLoad
{
    [super viewDidLoad];
    for (UIView *view in searchBar.subviews){
        for (UITextField *tf in view.subviews) {
            if ([tf isKindOfClass: [UITextField class]]) {
                tf.delegate = self;
                break;
            }
        }
    }
}

- (BOOL)textFieldShouldClear:(UITextField *)textField {
     // your code
    return YES;
}
1
Denis Redis

Je suggérerais d'utiliser les méthodes rightView et rightViewMode de UITextField pour créer votre propre bouton d'effacement utilisant la même image. Je suppose bien entendu qu'UISearchBar vous permettra d'accéder au champ UITextField qu'il contient. Je pense que ça va.
Soyez conscient de cela à partir de la bibliothèque de référence iPhone OS:

If an overlay view overlaps the clear button, however, the clear button always takes precedence in receiving events. By default, the right overlay view does overlap the clear button.

Vous devrez donc probablement également désactiver le bouton Clear original.

1
Andrew

N'a pas pu trouver de solution ici n'utilisant pas d'API privée ni de preuve de mise à niveau, car Apple change la structure d'affichage de UISearchBar. Voici ce que j'ai écrit qui fonctionne:

- (void)viewDidLoad {
    [super viewDidLoad];

    UITextField* textfield = [self findTextFieldInside:self.searchBar];
    [textfield setDelegate:self];
}

- (UITextField*)findTextFieldInside:(id)mainView {
    for (id view in [mainView subviews]) {
        if ([view isKindOfClass:[UITextField class]]) {
            return view;
        }

        id subview = [self findTextFieldInside:view];
        if (subview != nil) {
            return subview;
        }
    }

    return nil;
}

Puis implémentez le protocole UITextFieldDelegate dans votre classe et écrasez la méthode textFieldShouldClear:.

- (BOOL)textFieldShouldClear:(UITextField*)textField {
    // Put your code in here.
    return YES;
}

Modifier: Le fait de définir le délégué dans le champ de texte d'une barre de recherche dans iOS8 provoquera un blocage. Cependant, il semble que la méthode searchBar: textDidChange: soit appelée sur iOS8 en clear.

0
Steven Mattera

La meilleure solution de mon expérience est simplement de placer un UIButton (avec un fond clair et sans texte) au-dessus du bouton d'effacement du système et de connecter un IBAction.

- (IBAction)searchCancelButtonPressed:(id)sender {

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

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

}
0
Peter Lapisu