iphone ios uitableview contentoffset

iphone - UITableView contentOffSet no funciona correctamente



ios (15)

Debe ocultar la barra de búsqueda por sí mismo cuando desplaza la tabla. Así que no lo pongas como un encabezado de UITableView . Podría ocultarlo estableciendo su altura a cero. De esa manera, si la vista de la tabla está configurada para redimensionarse automáticamente, se expandirá.

En viewWillAppear , he agregado UISearchBar como mi headerview de UITableView . Cuando la vista se carga, UISearchbar en UINavigationBar usando contentOffSet de UITableView . Cuando el usuario abre la vista de tabla, se muestra la barra de búsqueda.

Después de agregar headerview lo oculto usando el código de abajo.

self.tableView.contentOffset = CGPointMake(0, 40); //My searhbar height is 40

Pero a veces contentOffSet no oculta la vista de cabecera. Cuál puede ser el error.


Después de una hora de pruebas, la única forma en que funciona al 100% es esta:

-(void)hideSearchBar { if([self.tableSearchBar.text length]<=0 && !self.tableSearchBar.isFirstResponder) { self.tableView.contentOffset = CGPointMake(0, self.tableSearchBar.bounds.size.height); self.edgesForExtendedLayout = UIRectEdgeBottom; } } -(void)viewDidLayoutSubviews { [self hideSearchBar]; }

con este enfoque siempre puedes ocultar la barra de búsqueda si está vacía


El problema es el enmascaramiento automático. Seleccione su tabla y asegúrese de haber seleccionado todas las líneas, como en la imagen de abajo.


El problema puede estar en el tamaño de la barra de búsqueda. Prueba la siguiente línea de código.

[searchBar sizeToFit];


En iOS 7/8/9 simple self.automaticallyAdjustsScrollViewInsets = NO; resuelto el problema en mi caso


En mi caso el problema fue que llamé.

[_myGreatTableView reloadData];

antes de obtener el _tableView.contentOffset.y . Esto siempre devolvió ''0''.

Así que cambié el orden de estos métodos y ahora funciona.

Este es un comportamiento bastante extraño en mi opinión, porque el desplazamiento devolvió 0 pero la interfaz de usuario aún mantuvo la posición de desplazamiento de la tabla.


En versiones anteriores del SDK de iOS, los métodos como viewWillAppear ejecutaban en el subproceso principal, ahora se ejecutan en un subproceso en segundo plano, por lo que ahora ocurre el problema.

La mayoría de las devoluciones de llamada tienden a dispararse en un hilo de fondo, así que siempre verifique la seguridad de los hilos cuando realice llamadas de UI.

Envíe el cambio al desplazamiento de contenido en el hilo principal:

C objetivo

dispatch_async(dispatch_get_main_queue(), ^{ CGPoint offset = CGPointMake(0, self.searchBar.bounds.height) [self.tableView setContentOffset:offset animated:NO]; });

Swift 3

DispatchQueue.main.async { let offset = CGPoint.init(x: 0, y: self.searchBar.bounds.height) self.tableView.setContentOffset(offset, animated: false) }


Esto funcionó para mí.

self.tableView.beginUpdates() self.tableView.setContentOffset( CGPoint(x: 0.0, y: 0.0), animated: false) self.tableView.endUpdates()

C objetivo :

[_tableView beginUpdates]; [_tableView setContentOffset:CGPointMake(0, 0)]; [_tableView endUpdates];


Esto funcionó para mí:

// contentOffset will not change before the main runloop ends without queueing it, for iPad that is dispatch_async(dispatch_get_main_queue(), ^{ // The search bar is hidden when the view becomes visible the first time self.tableView.contentOffset = CGPointMake(0, CGRectGetHeight(self.searchBar.bounds)); });

Póngalo en su -viewDidLoad o -viewWillAppear


La línea de código está funcionando como debería.

Explicación de contentOffset de un UITableView :

Por ejemplo, si tiene una vista de tabla de la altura 100. Su contenido puede ser más de lo que se ve, digamos 150. contentOffset le dirá a la tabla desde dónde debe comenzar el contenido. Diga contentOffset = (0, 40) , el contenido se mostrará después de 40 de su altura.

Nota: una vez que el contenido se desplaza, no afecta el contenido establecido anteriormente.


Lo arreglé con layoutIfNeeded ()

self.articlesCollectionView.reloadData() self.articlesCollectionView.layoutIfNeeded() self.articlesCollectionView.setContentOffset(CGPoint(x: 0, y: 40), animated: false)


No estoy seguro de cuál es el motivo (no tengo tiempo para investigarlo ahora), pero resolví este problema utilizando performSelector después de un retraso de 0. Ejemplo:

- (void)viewWillAppear:(BOOL)animated { ... [self performSelector:@selector(hideSearchBar) withObject:nil afterDelay:0.0f]; } - (void)hideSearchBar { self.tableView.contentOffset = CGPointMake(0, 44); }


Puede deberse al atributo "Ajustar inserciones de vista de desplazamiento" en el Controlador de vista. Vea esto: https://.com/a/22022366

EDITAR: Asegúrese de verificar el valor de ''contentInset'' para ver qué está sucediendo, ya que esto también tiene un efecto en la vista de desplazamiento. Este valor se modifica después de viewWillAppear: cuando se establece "Ajustar inserciones de vista de desplazamiento", que parece ser lo que otros intentan evitar mediante el uso de colas de envío y similares.


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, animated: false, scrollPosition: .Top)

Si coloca el código anterior en viewDidLoad , generará un error porque el tableView no se ha cargado todavía, por lo que debe ponerlo en viewDidAppear porque para este punto ya se ha cargado el tableView.

Si lo pone en viewDidAppear , cada vez que abra el tableView, se desplazará hacia la parte superior.

Tal vez no desee este comportamiento si el tableView permanece abierto, como cuando es un UITabBar View Controller o cuando realiza una sesión y luego vuelve. Si solo desea que se desplace hacia la parte superior de la carga inicial, puede crear una variable para verificar si se trata de una carga inicial para que se desplace hacia la parte superior solo una vez.

Primero defina una variable llamada isInitialLoad en la clase de controlador de vista y establézcala en "true":

var isInitialLoad = true

Y luego verifique si isInitialLoad es verdadero en viewDidAppear y si es verdadero, desplácese hasta la parte superior y establezca la variable isInitialLoad en false:

if isInitialLoad { let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0) self.tableView.selectRowAtIndexPath(firstIndexPath, animated: false, scrollPosition: .Top) isInitialLoad = false }


self.tableView.contentInset = UIEdgeInsetsMake(self.navigationController.navigationBar.frame.size.height -80, 0, 0, 0);