Usé Interface Builder para crear una vista de tabla, a la que agregué la barra de búsqueda de la biblioteca y el controlador de pantalla de búsqueda para agregar la funcionalidad de búsqueda. Sin embargo, IB lo configuró para que la barra sea visible en la parte superior de la pantalla cuando se muestre la vista por primera vez.
Me gustaría saber cómo hacer que la barra de búsqueda esté oculta de forma predeterminada pero que se pueda desplazar con la vista de tabla (consulte la aplicación Mail de Apple para ver un ejemplo). He intentado llamar scrollRectToVisible:animated:
en viewDidLoad
para desplazarse a la vista de tabla hacia abajo, pero fue en vano. ¿Cuál es la forma preferida de ocultar la barra de búsqueda de forma predeterminada?
contentOffset
con cualquier valor se romperá si está empleando un diseño complejo de controlador de vista. No lo recomiendo.No agregue UISearchBar como una subvista de UITableView, esto no es necesario.
UITableView tiene una propiedad tableHeaderView que es perfecta para esto:
- (void) viewDidLoad { [super viewDidLoad]; self.searchBar = [[[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)] autorelease]; self.searchBar.showsCancelButton = YES; self.searchBar.delegate = self; self.tableView.tableHeaderView = self.searchBar; }
Si no quiere verlo por defecto:
- (void) viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self.tableView setContentOffset:CGPointMake(0, 44)]; }
También obtengo el botón cancelar para ocultarlo nuevamente .... (y quitar el teclado)
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { [self.tableView setContentOffset:CGPointMake(0, 44) animated:YES]; [self.searchBar resignFirstResponder]; }
fuente
viewWillAppear
es una mala idea porque se ejecutará cada vez que navegue de regreso a su vista. Esto significa que la vista de la mesa se reducirá lentamente. ¡Insecto irritante!El contentOffset se señaló en los comentarios de Tim y Joe D'Andrea, pero esto se amplió un poco al agregar una animación para ocultar la barra de búsqueda. Noté que es un poco inesperado que la barra de búsqueda simplemente desaparezca.
Una pequeña actualización para aquellos que quieren apuntar a iOS 4.0 y superior, intente esto:
[UIView animateWithDuration:0.4 animations:^{ self.tableView.contentOffset = CGPointMake(0, self.searchDisplayController.searchBar.frame.size.height); } completion:nil];
Respuesta anterior:
[UIView beginAnimations:@"hidesearchbar" context:nil]; [UIView setAnimationDuration:0.4]; [UIView setAnimationBeginsFromCurrentState:YES]; self.tableView.contentOffset = CGPointMake(0, self.searchDisplayController.searchBar.frame.size.height); [UIView commitAnimations];
fuente
viewDidAppear:
lugar deviewDidLoad
.Hay muchas respuestas a esta solución, sin embargo, ninguna funcionó muy bien para mí.
Esto funciona perfectamente. Sin animación, y está hecho sobre
-viewDidLoad
- (void)viewDidLoad { [super viewDidLoad]; self.tableView.contentOffset = CGPointMake(0, self.searchBar.frame.size.height - self.tableView.contentOffset.y); }
Nota:
El código asume que tiene el
searchBar
@property
que está vinculado a la barra de búsqueda. Si no, puedes usarself.searchDisplayController.searchBar
en su lugarfuente
-viewWillAppear
no funciona. ¿Se llama cuando el controlador de pestañas cambia a la vista?Para Swift 3+
Hice esto:
Declare esto
var
:var searchController = UISearchController()
Y en el
viewDidLoad()
metodosearchController = UISearchController(searchResultsController: nil) searchController.searchResultsUpdater = self searchController.hidesNavigationBarDuringPresentation = false searchController.dimsBackgroundDuringPresentation = true searchController.searchBar.placeholder = NSLocalizedString("Search", comment: "") definesPresentationContext = true tableView.tableHeaderView = searchController.searchBar tableView.contentOffset = CGPoint(x: 0, y: searchController.searchBar.frame.size.height)
fuente
Mi objetivo era ocultar la barra de búsqueda agregada a tableHeaderView del estilo simple de TableView en el guión gráfico cuando se carga el controlador de vista y mostrar la barra cuando el usuario se desplaza hacia abajo en la parte superior de UITableView. Entonces, estoy usando Swift y he agregado una extensión:
extension UITableView { func hideSearchBar() { if let bar = self.tableHeaderView as? UISearchBar { let height = CGRectGetHeight(bar.frame) let offset = self.contentOffset.y if offset < height { self.contentOffset = CGPointMake(0, height) } } } }
en viewDidLoad () simplemente llame:
self.tableView.hideSearchBar()
fuente
Todas las soluciones existentes no funcionan para mí en iOS 8 cuando no hay suficientes filas para llenar el tableView ya que iOS ajustará el recuadro automáticamente en esta situación. (Sin embargo, las respuestas existentes son buenas cuando hay suficientes filas)
Después de perder como 6 horas en este tema, finalmente obtuve esta solución.
En resumen, debe insertar celdas vacías en tableView si no hay suficientes celdas, por lo que el tamaño del contenido de tableView es lo suficientemente grande como para que iOS no ajuste el recuadro por usted.
Así es como lo hice en Swift:
1.) declarar una variable
minimumCellNum
como propiedad de clasevar minimumCellNum: Int?
2.) Calcular
minimumCellNum
y un conjuntotableView.contentOffset
deviewWillAppear
let screenHeight = Int(UIScreen.mainScreen().bounds.height) // 101 = Height of Status Bar(20) + Height of Navigation Bar(44) + Height of Tab Bar(49) // you may need to subtract the height of other custom views from the screenHeight. For example, the height of your section headers. self.minimumCellNum = (screenHeight - 103 - heightOfOtherCustomView) / heightOfYourCell self.tableView.contentOffset = CGPointMake(0, 44)
3 en
tableView(tableView: UITableView, numberOfRowsInSection section: Int))
let numOfYourRows = YOUR LOGIC if numOfYourRows > minimumCellNum { return numOfYourRows } else { return minimumCellNum! }
4.) Registre una celda vacía, cuyo
selection
atributo esNone
, en el guión gráfico y entableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath)
if indexPath.row < numOfYourRows { return YOUR CUSTOM CELL } else { let cell = tableView.dequeueReusableCellWithIdentifier("EmptyCell", forIndexPath: indexPath) as! UITableViewCell return cell }
5.) en
tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
if tableView == self.tableView { if numOfYourRows < (indexPath.row + 1) { return } YOUR LOGIC OF SELECTING A CELL }
Esta no es una solución perfecta, pero es la única solución que realmente funciona para mí en iOS 8. Me gustaría saber si existe una solución más ordenada.
fuente
Nada de lo anterior funcionó para mí, así que en caso de que alguien tenga el mismo problema.
Lo he
searchBar
configurado comotableHeaderView
en una tabla agrupada en iOS7. EnviewDidLoad
tengotableView.contentOffset = CGPointMake(0, 44);
que mantenersearchBar
inicialmente "escondido". Cuando el usuario se desplaza hacia abajosearchBar
se visualizaObjetivo: ocultar la barra de búsqueda al tocar el botón cancelar
En
searchBarCancelButtonClicked(searchBar: UISearchBar!)
Esto no funcionó:
[yourTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
tableView se estaba desplazando demasiado hacia arriba, lo que provocó que la fila 0 fuera detrás de toolBar.Esto no funcionó:
tableView.ContentOffset = CGPointMake(0, 44)
- no pasa nadaEsto no funcionó:
tableView.ContentOffset = CGPointMake(0, searchBar.frame.size.height)
- no pasa nadaEsto no funcionó:
tableView.setContentOffset(CGPointMake(0, 44), animated: true);
nuevamente tableView se estaba desplazando demasiado hacia arriba, lo que resultó en que la fila 0 fuera detrás de toolBar.Esto funcionó parcialmente:
tableView.setContentOffset(CGPointMake(0, 0)
perotitleForHeaderInSection
iba detrás de toolBarESTO FUNCIONÓ:
tableView.setContentOffset(CGPointMake(0, -20)
No parece lógico, pero solo -20 lo movió a la posición correcta
fuente
CGRectGetHeight(searchBar.bounds)
?ContentOffset
soluciones funcionaráEl desplazamiento de contenido es el camino a seguir, pero no funciona el 100% del tiempo.
No funciona si se establece
estimatedRowHeight
en un número fijo. Todavía no conozco el trabajo. Creé un proyecto que muestra los problemas y creé un radar con Apple.Consulte el proyecto si quiere un ejemplo rápido de cómo configurarlo todo.
fuente
Tenga en cuenta que la respuesta aceptada se bloqueará si no hay datos en la vista de tabla. Y agregarlo a viewDidLoad puede no funcionar bajo ciertas circunstancias.
[yourTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO]; // crashes if no rows/data
Por lo tanto, en su lugar, agregue esta línea de código:
- (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [yourTableView setContentOffset:CGPointMake(0, self.searchDisplayController.searchBar.frame.size.height)]; }
fuente
Honestamente, ninguna de las respuestas realmente resolvió el problema (para mí). Si su vista de tabla no tiene filas O la altura de la fila es diferente, estas respuestas no son suficientes.
Lo único que funciona:
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; self.tableView.contentOffset = (CGPoint){.y = self.tableView.contentOffset.y + self.searchController.searchBar.frame.size.height}; }
fuente
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
.El
scrollToRowAtIndexPath
método provoca un bloqueo si no hay filas en la tabla.Sin embargo, UITableView es solo una vista de desplazamiento, por lo que simplemente puede cambiar el desplazamiento del contenido.
Esto verifica que tenga algo como su tableHeaderView, y asumiendo que hace desplazamientos para ocultarlo
if let searchHeight = tableView.tableHeaderView?.frame.height { tableView.setContentOffset(CGPoint.init(x: 0, y:searchHeight ), animated: false) }
fuente
Encuentro que la aplicación "Notas" no puede buscar elementos cuando tableView está en blanco. Así que creo que
-(void)addSubview:(UIView *)view
al principio solo se usa para agregar una tabla en blanco. Cuando agrega un elemento a su matriz de origen de datos, ejecutará otro fragmento de código para cargar tableView.Entonces mi solución es:
if([self.arrayList count] > 0) { [self.tableView reloadData]; //use jdandrea's code to scroll view when cell==nil in cellForRowAtIndexPath self.tableView.scrollEnabled = YES; } else { tableBlank = [[UITableView alloc]initWithFrame:CGRectMake(0,0,320,416) style:UITableViewStylePlain] autorelease]; tableBlank.delegate = self; tableBlank.dataSource = self; [self.view addSubview:tableBlank]; }
Espero que esto ayude :-)
fuente
Cambie los límites de tableView, esto se puede hacer dentro y
viewDidLoad
además no tiene que preocuparse por si la tabla está vacía o no (para evitar la excepción).CGRect newBounds = self.tableView.bounds; newBounds.origin.y = newBounds.origin.y + self.searchBar.bounds.size.height; self.tableView.bounds = newBounds;
Una vez que el usuario se haya desplazado hacia abajo en la tabla, la barra de búsqueda aparecerá y se comportará normalmente.
fuente
Las otras respuestas a esta pregunta no funcionaron en absoluto para mí, tuvieron un comportamiento extraño cuando tableView tenía 0 filas, o estropearon la posición de desplazamiento al ir y venir entre los elementos de línea principales y anidados. Esto funcionó para mí (el objetivo es ocultar el UISearchBar cuando está en carga):
public override func viewWillAppear(animated: Bool) { if self.tableView.contentOffset.y == 0 { self.tableView.contentOffset = CGPoint(x: 0.0, y: self.searchBar.frame.size.height) } }
Explicación
En cualquier momento
tableView
que aparezca, este código verifica si UISearchBar está visible (es decir, lay
posición decontentOffset
, también conocida como posición de desplazamiento, es0
). Si es así, simplemente se desplaza hacia abajo en la altura de la barra de búsqueda. Si la barra de búsqueda no está visible (piense en una lista más grande de elementostableView
), entonces no intentará desplazarsetableView
, ya que esto estropearía la posición cuando regrese de una línea de pedido anidada.Nota al
margen Recomendaría poner este código en un método separado para garantizar una responsabilidad única y darle la posibilidad de volver a utilizarlo en cualquier momento en su código.
fuente
Si su tabla siempre tendrá al menos una fila, simplemente desplácese hasta la primera fila de la tabla y la barra de búsqueda se ocultará automáticamente.
let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0)
self.tableView.selectRowAtIndexPath (firstIndexPath, animado: falso, scrollPosition: .Top)
Si coloca el código anterior en viewDidLoad , arrojará un error porque tableView aún no se ha cargado, por lo que debe ponerlo en viewDidAppear porque en este punto el tableView ya se ha cargado.
Si lo pones en viewDidAppear , cada vez que abras tableView, se desplazará hacia la parte superior.
Tal vez no desee este comportamiento si tableView permanece abierto, como cuando es un controlador de vista UITabBar o cuando hace una transición y luego regresa. Si solo desea que se desplace hacia la parte superior en la carga inicial, puede crear una variable para verificar si es una carga inicial para que se desplace hacia la parte superior solo una vez.
Defina primero una variable llamada isInitialLoad en la clase del controlador de vista y configúrela como "verdadero":
var isInitialLoad = true
Luego verifique si isInitialLoad es verdadero en viewDidAppear y si es verdadero, desplácese hasta la parte superior y establezca la variable isInitialLoad en falso:
if isInitialLoad { let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0) self.tableView.selectRowAtIndexPath(firstIndexPath, animated: false, scrollPosition: .Top) isInitialLoad = false }
fuente
El siguiente código me funciona
self.tableView.contentOffset = CGPointMake(0.0, 44.0);
fuente
Intenté configurar el desplazamiento de contenido y scrollToIndexpath pero nada funcionó satisfactoriamente. Eliminé la configuración de tableHeaderView como searchBar de viewDidLoad y la configuré en scrollview delegate como se muestra a continuación
override func scrollViewWillBeginDragging(scrollView: UIScrollView) { if scrollView.contentOffset.y < 0 && tableView.tableHeaderView == nil { tableView.tableHeaderView = searchController.searchBar tableView.setContentOffset(CGPointMake(0, scrollView.contentOffset.y + searchController.searchBar.frame.size.height), animated: false) } }
Esto funcionó a las mil maravillas La configuración de desplazamiento de contenido es para un desplazamiento suave
fuente
No olvide tener en cuenta la barra de estado y la barra de navegación . Mi controlador de vista de tabla está integrado en un controlador de navegación, en
viewDidAppear
:tableView.contentOffset = CGPointMake(0, -20) // -20 = 44 (search bar height) - 20 (status bar height) - 44 (navigation bar height)
trabajó para mi.
fuente
Para Swift:
Simplemente haga que el contenido de la vista de tabla y el desplazamiento, que debería ser como la altura de la barra de búsqueda.
self.tableView.contentOffset = CGPointMake(0, self.searchController.searchBar.frame.size.height)
fuente
Swift 3
¡También funciona con mesa vacía!
En mi entorno, cargo celdas personalizadas por archivo xib y rowHeight se configura automáticamente.
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { self.tableView.contentOffset = CGPoint(x: 0, y: self.tableView.contentOffset.y + self.searchController.searchBar.bounds.height) }
fuente
Tuve un problema similar. Y la única forma que encontré para resolver este problema fue usar el observador de valor clave en la propiedad contentOffset de UITableView.
Después de algunas depuraciones, me di cuenta de que el problema aparece solo si el tamaño del contenido de la vista de tabla es menor que la vista de tabla. Comienzo KVO cuando estoy en viewWillAppear. Y el envío detiene KVO 0.3 segundos después de que aparezca la vista. Cada vez que contentOffset se convirtió en 0.0, KVO reacciona y establece contentOffset en la altura de la barra de búsqueda. Dejo de KVO asincrónico después de 0.3 segundos porque el diseño de la vista restablecerá contentOffset incluso después de que aparezca la vista.
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self.tableView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil]; } -(void)viewDidAppear:(BOOL)animated{ __weak typeof (self) weakSelf = self; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [weakSelf.tableView removeObserver:self forKeyPath:@"contentOffset"];}); } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ if ([keyPath isEqualToString:@"contentOffset"] && self.tableView.contentOffset.y == 0.0) { self.tableView.contentOffset = CGPointMake(0, CGRectGetHeight(self.tableView.tableHeaderView.frame)); } } -(void)dealloc { [self.tableView removeObserver:self forKeyPath:@"contentOffset"]; }
fuente