Masquer une UISearchBar dans une UITableView [Résolu]

Sébastien M.Sébastien M. Membre
mars 2014 modifié dans API UIKit #1

Bonjour à  tous,


 


Je suis actuellement confronté a un problème qui me semblait initialement relativement simple et que je n'arrive pourtant pas à  résoudre.


 


Dans de nombreuses applications, on retrouve un UINavigationController contenant une UITableView ayant au dessus de ses cellules une UISearchBar. Cette dernière "se cache" généralement sous la UINavigationBar lorsque la première cellule se trouve tout en haut de la UITableView. C'est le comportement que l'on retrouve dans l'application "Notes".


 


Pour reproduire ce comportement, j'ai ajouté une UISearchView dans le tableViewHeader de ma UITableView. Et en effet, cela fonctionne parfaitement.


 


Cependant, il y a quelques jours, j'ai voulu rajouter quelques informations sous la UISearchBar. L'objectif étant que ces informations restent visibles et que seule la UISearchBar puisse "se cacher". J'ai donc modifié le contenu du tableViewHeader de l'UITableView : il contient désormais une UIView contenant elle même la UISearchBar. Et à  partir de ce moment là , ce qui fonctionnait si bien avant ne fonctionne plus du tout !


Après quelques tests, je me suis aperçu qu'à  partir du moment où le tableViewHeader n'est pas directement une UISeachBar, cela ne fonctionne plus. J'imagine que lorsque la UITableView détecte que son tableViewHeader contient une UISearchBar, elle adapte son comportement.


 


J'essaie donc de reproduire le comportement que j'ai décris au début de ce billet, mais je n'y arrive pas. J'ai, pour le moment, expérimenté deux solutions, qui ont chacune des soucis.


 


Ma première solution consiste à  modifier le contentInset lorsque la UISearchBar commence à  être masquée. Cependant, cela pose problème dès que l'on utilise les "sections indexes" :



- (void)viewWillAppear:(BOOL)animated
{
UIEdgeInsets insets;

[super viewWillAppear:animated];

if ([[self tableView] contentOffset].y < -20)
{
insets = [[self tableView] contentInset];
[[self tableView] setContentInset:UIEdgeInsetsMake(20, insets.left, insets.bottom, insets.right)];
[[self tableView] setContentOffset:CGPointMake(0, -20)];
}
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
UIEdgeInsets insets;

if ([[self tableView] contentOffset].y <= -20 && [[self tableView] contentOffset].y > -64)
{
insets = [[self tableView] contentInset];
[[self tableView] setContentInset:UIEdgeInsetsMake(- [[self tableView] contentOffset].y, insets.left, insets.bottom, insets.right)];
}
}

Ma seconde solution est plus simple et me parait mieux à  tous points de vue. Malheureusement, elle ne fonctionne pas lorsque très peu de cellules sont affichées :



- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];

if ([[self tableView] contentOffset].y < -20)
[[self tableView] setContentOffset:CGPointMake(0, -20)];
}

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
if (targetContentOffset->y <= -20 && targetContentOffset->y > -64)
targetContentOffset->y = -20;
}

Auriez-vous une autre solution ? Ou auriez-vous des pistes qui pourraient m'aider ?


 


J'ai joint à  ce billet un projet de test permettant de voir mon soucis. En l'état, c'est la seconde solution qui est implémentée, la première étant commentée.


Réponses

  • Bonjour tout le monde.


     


    Après de nombreux autres essais infructueux, la seule solution que j'ai trouvée consiste à  mettre les informations se trouvant sous la UISearchBar dans la première cellule de la UITableView.


     


    Le plus gros soucis de cette méthode est la perte probable de performance : notamment si la cellule d'information n'a pas la même hauteur que celle de vos autres cellules. En effet, il devient nécessaire d'implémenter la méthode tableView:heightForRowAtIndexPath: de UITableViewDelegate, qui d'après la documentation, peut poser des soucis de performance pour une UITableView contenant plus de 1000 cellules.


Connectez-vous ou Inscrivez-vous pour répondre.