ios - UISearchDisplayController con displaysSearchBarInNavigationBar empuja la vista de resultados hacia abajo con navigationBar.translucent=false
ios7 (5)
1. Use Revelar, busque la capa de cobertura y se encontró que _UISearchDisplayControllerDimmingView
2.Encuentre la capa, modifique el marco correspondiente, se puede encontrar en el mapa visualizando con la subcapa searchResultsTableView de la misma vista.
- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller {
for(UIView * v in controller.searchResultsTableView.superview.subviews)
{
if([v isKindOfClass:[NSClassFromString(@"_UISearchDisplayControllerDimmingView") class]])
{
v.frame = CGRectMake(0,20,320,400); // modify the frame
NSLog(@"--------- %@",[v class]);
}
}
3. De manera similar, si necesita ajustar searchResultsTableView the frame, agregue el siguiente código en la
- (void)searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView
{
tableView.frame =CGRectMake(0, 20, 320, 480-64-44);
}
Estoy usando un UISearchDisplayController con la nueva característica de ios 7: muestra SearchBarInNavigationBar y las barras de navegación opacas. El controlador de visualización de búsqueda parece posicionar su vista incorrectamente.
Intenté conectarlo para delegar métodos y reposicionar, pero no puedo obtener la posición inicial correcta, ni al girar. Además, esto parece una solución descuidada.
He buscado sin fin en línea una solución a este problema, pero nada de lo que se recomendó funcionó en mi caso. Restablecer el marco de searchResultsTable no funcionó porque era origin.y ya estaba en 0. Cambiando el tipo de ContentInset funcionó, pero no corrigió la vista de superposición atenuada y causó problemas con la vista de desplazamiento de la tabla en la parte inferior (y barras). Finalmente conseguí un truco de trabajo mejor, aunque no es completamente ideal ya que los cambios de marco de la vista se notan brevemente, pero al menos la posición es correcta después de eso.
Usando Reveal.app, pude profundizar en la jerarquía de vistas de UISearchDisplayController para averiguar qué estaba pasando, y este fue el resultado en mi caso:
UISearchDisplayControllerContainerView
- UIView (0,0,320,504)
- UISearchResultsTableView
- UIView (0,20,320,44)
- UIView (0,64,320,440)
- _UISearchDisplayControllerDimmingView
Hago todo programáticamente, así que no estoy seguro de una solución para los NIB. Aquí están los conceptos básicos de cómo mi UISearchBar y UISearchDisplayController se configuran en mi método viewDidLoad
:
UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 0)];
searchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
searchBar.delegate = self;
[searchBar sizeToFit];
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
self.searchController.delegate = self;
self.searchController.searchResultsDataSource = self.searchDataSource;
self.searchController.searchResultsDelegate = self;
if ([self.searchController respondsToSelector:@selector(displaysSearchBarInNavigationBar)]) {
self.searchController.displaysSearchBarInNavigationBar = YES;
}
Y mi hack que funcionó en este caso:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(fixSearchControllerPositionOnKeyboardAppear)
name:UIKeyboardWillShowNotification object:nil];
if (self.searchController.isActive) {
// the following is needed if you are return to this controller after dismissing the child controller displayed after selecting one of the search results
[self performSelector:@selector(fixSearchControllerPositionForiOS7) withObject:nil afterDelay:0];
}
}
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
}
- (void)fixSearchControllerPositionForiOS7 {
UIView *view = self.searchController.searchResultsTableView.superview;
// only perform hack if the searchResultsTableView has been added to the view hierarchy
if (view) {
// The searchDisplayController''s container view is already at 0,0, but the table view if shifted down 64px due to
// bugs with the subviews in iOS 7, so shift the container back up by that negative offset.
// This also fixes the position of the dimmed overlay view that appears before results are returned.
CGFloat yOffset = 64.0;
CGRect viewFrame = view.frame;
if (CGRectGetMinY(viewFrame) == 0) {
viewFrame.origin.y = -yOffset;
viewFrame.size.height += yOffset;
[UIView animateWithDuration:0.1 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
view.frame = viewFrame;
} completion:nil];
}
// we also need to adjust dimmed overlay view, so iterate through the search view controller''s container
// view and make sure all subviews have their vertical origin set to 0
UIView *searchContainerView = view.superview;
for (NSInteger i = 0; i < [searchContainerView.subviews count]; i++) {
UIView *subview = searchContainerView.subviews[i];
if (CGRectGetMinY(subview.frame) > 0) {
CGRect subviewFrame = subview.frame;
CGFloat offset = CGRectGetMinY(subviewFrame);
subviewFrame.origin.y = 0;
if (offset == 20.0) {
// this subview is partially responsible for the table offset and overlays the top table rows, so set it''s height to 0
subviewFrame.size.height = 0;
}
else {
// this subview is the dimmed overlay view, so increase it''s height by it''s original origin.y so it fills the view
subviewFrame.size.height += offset;
}
subview.frame = subviewFrame;
}
}
}
}
- (void)fixSearchControllerPositionOnKeyboardAppear {
// call hack to reset position after a slight delay to avoid UISearchDisplayController from overriding our layout fixes
[self performSelector:@selector(fixSearchControllerPositionForiOS7) withObject:nil afterDelay:0.1];
}
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
[self fixSearchControllerPositionForiOS7];
}
}
Tuve que agregar un observador para cuando aparezca el teclado ya que esto estaba causando que el UISearchDisplayController rediseñara sus subvistas, junto con un breve retraso para asegurar que mis ajustes de posición se aplicaran después de que UISearchDisplayController hiciera su diseño.
Simplemente habilite "Bajo barras opacas" en el guión gráfico de su controlador de vista o si desea codificar. Luego agregue las siguientes líneas. Su bien :)
self.edgesForExtendedLayout = UIRectEdgeAll;
self.extendedLayoutIncludesOpaqueBars = YES;
Tuve el mismo problema y lo he arreglado de esta manera:
- Subclase UISearchDisplayController para tener la barra UISearch en la barra de navegación para iOS 6 y 7. He sobrescrito:
-(void)setActive:(BOOL)visible animated:(BOOL)animated { if (SYSTEM_VERSION_LESS_THAN(@"7")) { if(self.active == visible) return; [self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO]; if (visible) { [self.searchBar becomeFirstResponder]; } else { [self.searchBar resignFirstResponder]; } } else { self.searchContentsController.view.frame = CGRectMake(0, 0, kCurrentScreenWidth, kCurrentScreenHeight); [super setActive:visible animated:animated]; } }
2.En el UISearchDisplayDelegate he añadido esto:
- (void) searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView { // iOS7 Hack if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7")) { controller.searchResultsTableView.contentInset = UIEdgeInsetsMake(0.f, 0.f, 0.f, 0.f); } } - (BOOL) searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString { // -- iOS 7 Hack if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7")) { controller.searchResultsTableView.frame = CGRectMake(0, 64, kCurrentScreenWidth, kCurrentScreenHeight-64); [controller.searchContentsController.view setNeedsLayout]; } }
Tuve el mismo problema y, después de horas de buscar una respuesta, decidí analizar la jerarquía de vistas. Parece que la vista de supervisión de la barra de búsqueda, que también es la vista atenuada, tiene un origen de 64 y una altura de 504, que no está poblando toda la pantalla. No estoy seguro de por qué es así. Sin embargo, terminé configurando la y en 0 y su altura a la altura de la pantalla. Después de lo cual, vuelvo a establecer su y en el valor original o, de lo contrario, la vista de la tabla de contenido se distorsionará. No es la mejor solución, pero es mejor que nada. Espero que esto te ayude.
- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
self.savedSearchTerm = nil;
UIView *dimmedView = controller.searchBar.superview;
CGRect frame = dimmedView.frame;
frame.origin.y = 64;
dimmedView.frame = frame;
[self.tableView reloadData];
}
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
UIView *dimmedView = controller.searchBar.superview;
CGRect frame = dimmedView.frame;
frame.origin.y = 0;
frame.size.height = 568;
dimmedView.frame = frame;
}