Lorsqu'un utilisateur commence à modifier une barre de recherche de UISearchDisplayController
, le contrôleur de recherche devient actif et masque la barre de navigation de la vue tout en présentant la vue de table de recherche. Est-il possible d'empêcher une UISearchDisplayController
de masquer la barre de navigation sans la réimplémenter?
La nouvelle classe UISearchController
introduite avec iOS 8 a une propriété hidesNavigationBarDuringPresentation
que vous pouvez définir sur false si vous souhaitez que la barre de navigation reste visible (par défaut, elle reste masquée).
Je viens juste de déboguer un peu dans UISearchDisplayController et de constater qu'il appelle une méthode privée sur UINavigationController pour masquer la barre de navigation. Cela se produit dans -setActive: animated :. Si vous sous-classez UISearchDisplayController et remplacez cette méthode par le code suivant, vous pouvez empêcher le masquage de navigationBar en simulant son masquage.
- (void)setActive:(BOOL)visible animated:(BOOL)animated;
{
if(self.active == visible) return;
[self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
[super setActive:visible animated:animated];
[self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
if (visible) {
[self.searchBar becomeFirstResponder];
} else {
[self.searchBar resignFirstResponder];
}
}
Faites-moi savoir si cela fonctionne pour vous. J'espère aussi que cela ne se cassera pas dans les futures versions d'iOS ... Testé sur iOS 4.0 uniquement.
La solution la plus simple et sans hacks.
@interface MySearchDisplayController : UISearchDisplayController
@end
@implementation MySearchDisplayController
- (void)setActive:(BOOL)visible animated:(BOOL)animated
{
[super setActive: visible animated: animated];
[self.searchContentsController.navigationController setNavigationBarHidden: NO animated: NO];
}
@end
Les réponses ci-dessus ne fonctionnaient pas bien pour moi. Ma solution consiste à faire croire à UISearchDisplayController qu’il n’existait pas de UINavigationController.
Dans votre contrôleur de vue, ajoutez cette méthode
- (UINavigationController *)navigationController {
return nil;
}
Cela n'a pas eu d'effets secondaires indésirables pour moi, bien que cela semble être une très mauvaise idée ... Si vous devez accéder au contrôleur de navigation, utilisez [super navigationController]
.
Depuis iOS 8.0, le même comportement peut être obtenu en définissant la propriété self.searchController.hidesNavigationBarDuringPresentation
de UISearchController
sur False.
Le code dans Swift ressemble à ceci:
searchController.hidesNavigationBarDuringPresentation = false
Essayé cela d'une manière différente, sans sous-classe UISearchDisplayController. Dans votre classe UIViewController où vous définissez le délégué pour UISearchDisplayController, implémentez searchDisplayControllerDidBeginSearch: et ajoutez use
[self.navigationController setNavigationBarHidden:NO animated:YES];
A fait le tour pour moi, espérons que cela aide.
Je me suis heurté à cela tout en abordant un problème légèrement différent. Lors de l’utilisation de UISearchDisplayController, je souhaite que la barre de recherche soit in la barre de navigation (pas sous).
Il n'est pas difficile de placer la barre de recherche dans la barre de navigation (voir UISearchBar et UINavigationItem ). Cependant, UISearchDisplayController suppose que la barre de recherche est toujours sous la barre de navigation et insiste (comme indiqué ci-après) sur le fait de masquer la barre de navigation lors de la saisie du mot recherche pour que les choses soient terribles. De plus, UISearchDisplayController rend la barre de recherche plus claire que la normale.
J'ai trouvé une solution. L'astuce consiste à libérer UISearchDisplayController (de manière contre-intuitive) du contrôle de toute barre UISearchBar. Si vous utilisez xibs, cela signifie la suppression de l’instance de la barre de recherche ou au moins le décrochage de la prise. Ensuite, créez votre propre UISearchBar:
- (void)viewDidLoad
{
[super viewDidLoad];
UISearchBar *searchBar = [[[UISearchBar alloc] init] autorelease];
[searchBar sizeToFit]; // standard size
searchBar.delegate = self;
// Add search bar to navigation bar
self.navigationItem.titleView = searchBar;
}
Vous devez activer manuellement le contrôleur d'affichage de la recherche lorsque l'utilisateur appuie sur la barre de recherche (en -searchBarShouldBeginEditing:
) et le fermer manuellement lorsque l'utilisateur termine la recherche (en -searchDisplayControllerWillEndSearch:
).
#pragma mark <UISearchBarDelegate>
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
// Manually activate search mode
// Use animated=NO so we'll be able to immediately un-hide it again
[self.searchDisplayController setActive:YES animated:NO];
// Hand over control to UISearchDisplayController during the search
searchBar.delegate = (id <UISearchBarDelegate>)self.searchDisplayController;
return YES;
}
#pragma mark <UISearchDisplayDelegate>
- (void) searchDisplayControllerDidBeginSearch:(UISearchDisplayController
*)controller {
// Un-hide the navigation bar that UISearchDisplayController hid
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
- (void) searchDisplayControllerWillEndSearch:(UISearchDisplayController
*)controller {
UISearchBar *searchBar = (UISearchBar *)self.navigationItem.titleView;
// Manually resign search mode
[searchBar resignFirstResponder];
// Take back control of the search bar
searchBar.delegate = self;
}
iOS 7 bousille un peu les choses ... pour moi cela fonctionnait parfaitement:
/**
* Overwrite the `setActive:animated:` method to make sure the UINavigationBar
* does not get hidden and the SearchBar does not add space for the statusbar height.
*
* @param visible `YES` to display the search interface if it is not already displayed; NO to hide the search interface if it is currently displayed.
* @param animated `YES` to use animation for a change in visible state, otherwise NO.
*/
- (void)setActive:(BOOL)visible animated:(BOOL)animated
{
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
[super setActive:visible animated:animated];
[self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
[[UIApplication sharedApplication] setStatusBarHidden:NO];
}
La raison pour afficher/masquer la barre d'état
Vraiment belle solution, mais mon application était en panne sous iOS6. J'ai dû faire la modification suivante pour que cela fonctionne.
@implementation ICSearchDisplayController
- (void)setActive:(BOOL)visible animated:(BOOL)animated
{
if (visible == YES) {
[super setActive:visible animated:animated];
[self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
} else {
[super setActive:NO animated:NO];
}
}
Cela semble le résoudre pour moi. Testé sous iOS5/6.1. Aucun problème visuel que je pouvais voir.
- (void)viewDidAppear
{
[super viewDidAppear];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillAppear:) name:UIKeyboardWillShowNotification object:nil];
}
-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)keyboardWillAppear:(NSNotification *)notification
{
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
-(void)viewDidLayoutSubviews{
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
Je pense que la meilleure solution consiste à implémenter UISearchDisplayController vous-même.
Ce n'est pas si difficile. Vous devez seulement implémenter UISearchBarDelegate pour votre UIViewController et inclure un UITableView pour afficher vos résultats de recherche.
J'ajoutais une barre de navigation personnalisée sur mon ViewController qui devenait cachée lors de la recherche; une solution rapide, mais pas si bonne, était
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
[self.view addSubview:_navBar];
}
_navBar est UINavigationBar ajouté par programme, ce qui m'a aidé à me cacher de la barre de navigation.
Comme l'a souligné jrc, "dissocier UISearchDisplayController de tout contrôle UISearchBar" semble fonctionner pour moi. Si je passe nil en tant que paramètre lors de la création de UISearchDisplayController, la barre de navigation reste visible à tout moment:
searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:nil contentsController:self];
@ Pavel fonctionne parfaitement bien. Cependant, j'essayais de placer cela dans un UIPopoverController et le texte du champ est légèrement poussé lorsque le champ de texte de la barre de recherche devient le premier répondeur. Cela semble un peu moche. Je l'ai donc corrigé en appelant la méthode super
avec .animated
mis à NO
.
Je voulais juste ajouter à Stigi réponse. Lorsque vous annulez la recherche et recommencez la recherche - le tableau des résultats de la recherche ne réagira pas au toucher. Vous devez donc ajouter la ligne suivante.
self.searchResultsTableView.alpha = 1;
Donc, le code mis à jour ressemble à la suivante
- (void)setActive:(BOOL)visible animated:(BOOL)animated;
{
if(self.active == visible) return;
if (visible) {
[self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
[super setActive:visible animated:animated];
[self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
self.searchResultsTableView.alpha = 1;
[self.searchBar becomeFirstResponder];
} else {
[super setActive:visible animated:animated];
[self.searchBar resignFirstResponder];
}
}