web-dev-qa-db-fra.com

Changer la taille du UISearchBar TextField?

J'ai un UITableView avec un index sur le côté; Je souhaite y ajouter un UISearchBar, mais l'index chevauche le "x" pour effacer la recherche. J'ai remarqué que dans l'application Contacts, le champ de texte de la barre UISearchBar est redimensionné pour s'adapter à cela, mais je ne peux pas déterminer comment le faire dans ma propre application.

J'ai essayé ce qui suit dans mon viewDidLoad, mais cela ne semble pas fonctionner.

UITextField * textField = (UITextField *)[[self.search subviews] objectAtIndex:0];
CGRect r = textField.frame;

[textField setFrame:CGRectMake(r.Origin.x, r.Origin.y, r.size.height, r.size.width-30)];

Des idées?

30
Padraig

c'est beaucoup plus facile que toutes ces suggestions. Dans le générateur d'interface, au lieu de placer la barre de recherche comme en-tête de votre vue Table, vous pouvez placer une vue. Ensuite, placez une barre de navigation dans cette vue. Saisissez la poignée de redimensionnement gauche de la barre de navigation et tirez-la vers la droite jusqu'à ce que le point N B ne mesure que 25 pixels de large. Effacez le titre dans le N B (double-cliquez dessus pour le sélectionner, puis supprimez-le). Ajoutez ensuite une barre de recherche dans la même vue. Déplacez sa poignée de redimensionnement droite vers la gauche, ajustez-la de sorte qu'elle bute sur le NB.

Vous pouvez également activer un bouton d’annulation si vous le souhaitez. Il ne chevauchera pas non plus l’index (reste dans la barre de recherche).

Apparemment, une vue sous forme de tableau ne peut contenir qu'une seule sous-vue, c'est pourquoi vous devez d'abord placer la vue, puis le N B et la barre de recherche à l'intérieur.

UPDATE: reportez-vous à Début de développement iPhone depuis Apress, p. 241 de l'édition 3 du SDK. Vous venez de désactiver l'index lors de la recherche.

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    if (isSearching) {
        return nil;
    }
    return keys;
}

En outre, ils parlent d'ajouter une loupe en haut de l'index.

Grand livre tout autour.

30
Mike

Pourquoi ne pas simplement réduire la barre UISearchBar horizontalement et placer une barre UINavigationBar (vide) à droite de celui-ci? Ils rendront exactement le même fond.

Mieux que de pirater les objets internes d’Apple qui pourraient changer.

De plus, lors de l'animation de la largeur de la barre UISearchBar, vous remarquerez que le champ de texte intérieur n'est pas animé avec lui. Vous pouvez résoudre ce problème en appelant le "layoutSubviews" de UISearchBar dans votre bloc d'animation après avoir modifié son image. (c'est là qu'il détermine la taille du champ de texte intérieur)

16
Nick Farina

Ok, j'ai trouvé une solution.

  1. Créer une sous-classe de UISearchBar
  2. Incluez ce code dans la méthode drawRect:.

    UITextView * textField = [self.subviews objectAtIndex:0];
    textField.frame = CGRectMake(5, 6, (310 - kRightSideMargin), 31); 
    
    [super drawRect:rect];
    

Remarque: kRightSideMargin est une constante que j'ai définie dans mon fichier d'en-tête. Je l'ai mis à 25.

Merci pour les suggestions de tous les autres.

8
Padraig

Depuis iOS 6, la solution de barre de navigation ne fonctionnait pas bien pour moi en raison d'apparences légèrement différentes entre UISearchBar et UINavigationBar. Donc, je suis passé à quelque chose de similaire à l'approche de Padraig en sous-classant le UISearchBar.

@interface SearchBarWithPad : UISearchBar
@end


@implementation SearchBarWithPad
- (void) layoutSubviews {

    [super layoutSubviews];
    NSInteger pad = 50;
    for (UIView *view in self.subviews) {
        if ([view isKindOfClass: [UITextField class]])
        view.frame = CGRectMake (view.frame.Origin.x, view.frame.Origin.y, view.frame.size.width - pad, view.frame.size.height);
    }   
}
@end

Edit: Ah, je ne l’ai pas essayé, mais je pense que vous pourrez peut-être définir le clipToBounds = YES d’une barre de navigation pour désactiver sa nouvelle ombre, créant ainsi à nouveau un aspect cohérent entre les deux contrôles.

6
Ernie Thomason

Comme Padraig l'a fait remarquer, tout ce que vous avez à faire est de sous-classer le searchBar. Créez votre sous-classe UISearchBar et ajoutez le code suivant à la méthode layoutSubviews:

- (void)layoutSubviews
{
    UITextField *searchField;

    for(int i = 0; i < [self.subviews count]; i++)
    {
        if([[self.subviews objectAtIndex:i] isKindOfClass:[UITextField class]])
        {
            searchField = [self.subviews objectAtIndex:i];
        }
    }

    if(!(searchField == nil))
    {
        searchField.frame = CGRectMake(4, 5, 285, 30); 
    }
}

Cela parcourt toutes les sous-vues et les compare au type UITextField. De cette façon, si elle se déplace dans sa gamme de vues secondaires, elle sera toujours saisie. J'ai trouvé 285 juste assez large pour ne pas chevaucher l'index de mon tableView.

6
timmytheRock

J'utilise ViewDeck et souhaite afficher une UISearchbar inside the leftController.

Maintenant, le problème est que si j'ouvre le côté gauche qui contient la navigation, le bit de droite chevauche mon champ de recherche.

Je me suis débarrassé de cela en écrivant UISearchBar, le champ de texte aura toujours la même largeur, mais dans un cas, le ViewDeck se chevauchant et dans l'autre cas, je cache le bit ViewDeck, puis le bouton d'annulation occupe l'espace suivant:

Sous-classe UISearchBar

#import "ViewDeckSearchBar.h"
#define kViewDeckPadding 55

@interface ViewDeckSearchBar()
@property (readonly) UITextField *textField;
@end

@implementation ViewDeckSearchBar

static CGRect initialTextFieldFrame;

- (void) layoutSubviews {

    [super layoutSubviews];

    // Store the initial frame for the the text field
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        initialTextFieldFrame = self.textField.frame;
    });

    [self updateTextFieldFrame];
}

-(void)updateTextFieldFrame{

    int width = initialTextFieldFrame.size.width - (kViewDeckPadding + 6);
    CGRect newFrame = CGRectMake (self.textField.frame.Origin.x,
                                  self.textField.frame.Origin.y,
                                  width,
                                  self.textField.frame.size.height);

    self.textField.frame = newFrame;
}

-(UITextField *)textField{
    for (UIView *view in self.subviews) {
        if ([view isKindOfClass: [UITextField class]]){
            return (UITextField *)view;
        }
    }

    return nil;
}

@end

Classe ViewController

Dans ma classe de navigation, je dois écraser ces deux méthodes UISearchbarDelegate pour pouvoir accéder au mode plein écran avec les résultats de la recherche:

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar{

    [self.viewDeckController setLeftSize:0];

    // I am also using scopes, which works fine (they fade out when not searching)
    self.searchBar.scopeButtonTitles = @[@"Food",
                                         @"Beverages",
                                         @"Misc"];
}

-(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar{
    self.viewDeckController.leftSize = 55;
}

Résultat

ViewDeck montrant à droite:

a http://i5.minus.com/jA34MnXVqPZez.png

Rechercher en plein écran (le bouton et les boutons de la portée sont animés dans).

a http://i2.minus.com/jjKEgXLur1kH6.png

5
Besi

Désolé de faire glisser tout cela à nouveau.

Je voulais que UISearchBar soit plus court et j'utilise un UISearchBarController, mais sans vouloir réellement l'index. C'est parce que j'ai un calque à droite:

Long search bar

Pour ce faire, je simule un sectionIndex avec un élément vide, puis le cache. Voici comment je fais ça:

 - (void)hideTableIndex {
    for (UIView *view in [tableView subviews]) {
        if ([view isKindOfClass:NSClassFromString(@"UITableViewIndex")]) {
            view.hidden = YES;
        }
    }
 }

 - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)aTableView {
    if (aTableView == self.searchDisplayController.searchResultsTableView) {
        return nil;
    } else {
        [self performSelector:@selector(hideTableIndex) withObject:nil afterDelay:0];
        return [NSArray arrayWithObjects:@"", nil];
    }
 }

 - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
    return 0;
 }

Cela raccourcit le UISearchBar et masque l'index afin qu'il ne puisse pas être exploité (une petite section passerait sinon à la gauche de la superposition qui, une fois engagée, ferait défiler UITableView vers le haut). Comme ça:

alt text

Mieux encore, lorsque vous utilisez la recherche, vous obtenez toujours la barre de largeur complète:

alt text

2
Alastair Stuart

Il suffit de mettre un UIView et de placer la barre de recherche à l'intérieur de ce UIView. UIView doit être de la même taille que UISearchBar ..__ cela a fonctionné pour moi.

2
Ideveloper

Désolé pour le nécropostage, mais j'ai trouvé un autre moyen de faire un petit espace à droite du champ de texte ..__J'ai eu le problème, j'avais une tableview indexée avec une barre de recherche comme première ligne. À présent, l'index et la barre de recherche (créés dans IB, au fait) se chevauchaient. Il a presque tout essayé sans succès. Il semble que les propriétés width et height du textifield ne répondent pas ... Je suis donc venu avec ceci:

searchBar.showsCancelButton = YES;

UIView *cButton = [searchBar.subviews objectAtIndex:2];

cButton.hidden = YES;

Je ne peux toujours pas ajuster la taille de l'espace, mais cela le fait pour le moment ... bien que ... solution assez étrange ...

1
swissdude

Tout le monde a fourni des moyens de modifier l'interface utilisateur. J'ai découvert comment obtenir des résultats identiques. Vous devez fournir les deux implémentations suivantes:

  1. Utilisez UISearchDisplayController Plus important encore, assurez-vous de l’initialiser avec:

- (id)initWithSearchBar:(UISearchBar *)searchBar contentsController:(UIViewController *)viewController

Si vous ne définissez pas une barre UISearchBar valide (ou que vous passerez la valeur nil), cela empêchera l'ajustement du champ UITextField pour l'index.

  1. Vous devez retourner un tableau valide de titres en implémentant:

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView;

Si vous renvoyez nil, l'index ne sera pas affiché et le champ UITextField ne sera pas correctement ajusté.

J'ai soumis un rapport de bogue à Apple, suggérant qu'il semble logique que seul le n ° 2 soit requis, et non le n ° 1. Je n'ai rien trouvé dans la Human Interface Guideline (iPhone HIG) nécessitant l'utilisation de UISearchDisplayController.

1
Mark

Le champ de texte utilisé dans UISearchBar est une sous-classe de UITextField appelée UISearchBarTextField.

Autant que je sache, il n’existe aucun moyen de redimensionner UISearchBarTextField à l’aide de l’API publique, et l’API private ne révèle pas grand chose non plus.

Peut-être pouvez-vous jeter un coup d'œil aux sous-vues de UISearchBarTextField, si elles en ont.

UPDATE: Ce n'est pas le cas.

UPDATE 2: Je pense que vous devriez jeter un coup d'œil à la propriété rightView de UITextField. Le code ci-dessous, bien que cela ne fonctionne pas, semble être un bon point de départ:

UIView *emptyView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 25, 25)];
[textField setRightView:emptyView];
[textField setRightViewMode:UITextFieldViewModeAlways];
[emptyView release];
1
Can Berk Güder

La clé consiste à utiliser la "barre de recherche et le contrôleur d'affichage de recherche" et non la "barre de recherche" lors de l'utilisation d'Interface Builder.

1
Graeme Wicksted

Ce que je viens de dire n'est pas trop mieux. Fondamentalement, je crée une vue vide avec le cadre que je souhaite utiliser pour la barre de recherche. Ensuite, je crée un UIToolbar pour aller derrière la barre de recherche. Assurez-vous de définir son cadre sur le même cadre que UIView, sauf que la valeur Y doit être -1; sinon, vous aurez deux frontières tracées en haut. Créez ensuite votre UISearchBar, mais définissez la largeur du cadre sur 30 (ou ce qui convient à votre application) inférieure à UIView. Ajoutez-les en tant que sous-vues et définissez votre UIView en tant que tableHeaderView.

0
Jeff Kelley

J'ai suivi les conseils de Mike en créant UIView, puis en y insérant une barre de navigation et une barre UISearch. Seul problème, c’est la première fois que la barre de recherche est affichée, son arrière-plan est identique à celui d’une barre de navigation.

Fait intéressant, si j'active la recherche, puis cliquez sur Annuler le fond de cette "fixe" !?

J'utilise le SDK 3.0. J'ai donc supprimé l'élément UISearchBar créé lorsque j'ai fait glisser un contrôleur UISearchDisplayController vers mon NIB, puis j'ai créé la vue comme décrit ci-dessus et je l'ai connecté au propriétaire du fichier et à la sortie searchBar du contrôleur d'affichage de recherche.

0
petert

Une autre approche (fastidieuse) serait de redimensionner la barre de recherche et de combler le «vide» avec une barre de navigation. Travaille pour moi.

0
Bart Jacobs

On dirait qu’Apple redimensionne la vue (notez que l’index est animé à droite, en dehors de l’écran), ce qui le rend plus grand que l’écran.

J'imagine qu'il vous faudrait implémenter la méthode searchBarTextDidBeginEditing: de la UISearchBarDelegate pour déclencher cela au moment approprié. Cela ne semble toutefois pas un peu compliqué, mais il existe peut-être une meilleure façon de le faire.

0
Stephen Darlington