Comment supprimer le fond de UISearchBar et customiser le fond de son searchField

Il est assez largement admis que beaucoup d’élément sur iOS 6.1 et les version précédentes sont très complexes à customiser. Apple a ajouté la possibilité d’utiliser l’apparence pour modifier les éléments les plus laborieux, tels que UINavigationBar et UINavigationItem, mais il y a encore des éléments auxquels il est difficile de toucher, surtout avant la version 5 de Xcode.

Je vais aujourd’hui vous montrer comment j’ai réussi à retirer tous les fonds de UISearchBar, afin de pouvoir utiliser cet élément par dessus n’importe quoi sans mettre de fond (ce qui peut être voulu dans certains cas, mais n’est pas toujours ce dont on a besoin).

Customiser UISearchBar

UISearchBar classique
L’aspect classique de UISearchBar

Chaque développeur iOS a forcement le souvenir d’au moins un combat épique avec les couleurs de teinte et les couleurs ou images de fond, avant de jeter l’éponge et de s’en tenir à une solution qui n’était pas si mal, mais clairement pas parfaite (soit en capitulant et utilisant la teinte, ou simplement en n’utilisant pas du tout UISearchBar et en réinventant la roue). Le problème avec UISearchBar, c’est que changer sa couleur de fond n’a pas d’effet, et modifier sa teinte ne retire pas son gradient. En revanche, modifier son image de fond fonctionne assez bien.

L’idée ici est d’utiliser l’image de fond pour obtenir ce que l’on veut d’UISearchView. En supposant que vous avez créé votre UISearchView soit dans le code, soit dans un xib en le liant correctement dans le .h, voici ce que vous devez faire :


- (void)viewDidLoad
{
    [super viewDidLoad];
    // 1
    UIImage* clearImg = [CDViewController imageWithColor:[UIColor clearColor] andHeight:32.0f];
    // 2
    [_searchBar setBackgroundImage:clearImg];
    // 3
    [_searchBar setSearchFieldBackgroundImage:clearImg forState:UIControlStateNormal];
    // 4
    [_searchBar setBackgroundColor:[UIColor clearColor]];
}

+ (UIImage*) imageWithColor:(UIColor*)color andHeight:(CGFloat)height
{
    CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, height);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetFillColorWithColor(context, [color CGColor]);
    CGContextFillRect(context, rect);

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return image;
}

Il se passe plusieurs choses ici :

1/ On créé une image de taille 1×32 remplie de couleur transparente. Au début, j’ai tenté avec une image qui faisait 1×1, mais j’ai vite réalisé que lorsqu’elle est mise sur le searchField, celui-ci n’est étiré qu’horizontalement, et cela fera simplement disparaitre le texte dans la UISearchBar, sauf pour une ligne d’1px, où se trouve cette image de fond.

2/ On définit cette image comme fond de notre UISearchBar.

3/ On définit cette image comme fond du searchField.

4/ On définit la couleur de fond de SearchBar à clearColor.

Qui plus est, ce serait une bonne idée d’avoir la fonction imageWithColor:andHeight: dans une catégorie sur UIImage, afin de pouvoir l’utiliser n’importe où dans votre projet !

UISearchBar avec un fond clearColor
Voici le résultat de cette opération

Comme vous pouvez le voir, on ne met plus vraiment en avant le fait que ce soit une zone textField. Pour résoudre ce souci, nous avons plusieurs options. Nous pouvons définir la couleur du fond de _searchBar à tout sauf clearColor, mais cela signifierait que sa taille serait bloquée à 44px. Des options plus flexibles serait de soit mettre une vue colorée de la taille désirée derrière notre UISearchBar, soit, si on ne veut pas ajouter plus de code, définir une UIImage colorée de 1x32px (ou toute autre taille désiré) comme fond de searchField :

Notre UISearchBar customisée
Voici ce à quoi ressemble notre UISearchBar custom après nos modifications

Définir comme apparence par défaut

Afin de faire de cela l’apparence par défaut de toutes les UISearchBars de l’application, utilisons la puissance de [UISearchBar appearance], en appelant tout cela depuis notre AppDelegate ainsi :


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    UIColor* myColor = [UIColor colorWithRed:0 green:0.48 blue:1 alpha:1]; // set your desired background color here

    UIImage* clearImg = [CDViewController imageWithColor:[UIColor clearColor] andHeight:1.0f];
    UIImage* coloredImg = [CDViewController imageWithColor:myColor andHeight:32.0f];

    [[UISearchBar appearance] setBackgroundColor:[UIColor clearColor]];
    [[UISearchBar appearance] setBackgroundImage:clearImg];
    [[UISearchBar appearance] setSearchFieldBackgroundImage:coloredImg forState:UIControlStateNormal];

    return YES;
}

Et voilà, l’affaire et dans le sac !

Notes

Quand j’ai écris cet article, j’ai rencontré moins de problèmes que lorsque j’ai résolu cette énigme la première fois que je l’ai rencontrée. En fait, lorsque j’ai ajouté la UISearchBar, j’ai coché « Show Scope Bar » dans Interface Builder, avant de le décocher. Faire cela ajoute automatiquement un contrôle segmenté avec deux boutons dont les titres sont « title ». Faites-y donc attention et supprimez-les si vous n’avez pas besoin d’utiliser la Scope Bar, autrement cela salira votre travail.

Voici, en utilisant Spark Inspector, le contenu de votre UISearchBar si vous montrez puis cachez la Scope Bar par erreur :

UISearchBar avec une Scope Bar cachée dans Spark Inspector
UISearchBar avec une Scope Bar cachée dans Spark Inspector

On peut voir le contrôle segmenté, juste derrière le fond de notre UISearchBar et celui de searchField. Si vous ne voulez pas avoir de fond derrière votre UISearchBar *et* utiliser la Scope Bar pour quelque raison que ce soit, voici ce que vous devez faire :


UIImage* clearImg = [CDViewController imageWithColor:[UIColor clearColor] andHeight:1.0f];

[_searchBar setScopeButtonTitles:nil];
[_searchBar setScopeBarBackgroundImage:clearImg];
[_searchBar setScopeBarButtonBackgroundImage:clearImg forState:UIControlStateNormal];
[_searchBar setScopeBarButtonDividerImage:clearImg forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal];

J’espère que cela aidera quelques ici bas. Merci de laisser un commentaire si vous avez trouvé une utilité à mon code, ou si vous avez remarque ou question à son sujet ! 😉

This post is also available in: Anglais

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.