ios uitableview animation uinavigationcontroller

Comportamiento extraño de uitableview en iOS11. Las celdas se desplazan hacia arriba con la animación de navegación



animation uinavigationcontroller (12)

Recientemente migré un código al nuevo SDK de iOS 11 beta 5.

Ahora tengo un comportamiento muy confuso de UITableView. La vista de tabla en sí no es tan elegante. Tengo celdas personalizadas, pero en su mayor parte es solo por su altura.

Cuando presiono mi controlador de vista con vista de tabla obtengo una animación adicional donde las celdas "se desplazan hacia arriba" (o posiblemente se cambia todo el marco de la vista de tabla) y hacia abajo a lo largo de la animación de navegación push / pop. Por favor vea gif:

Creo manualmente tableview en el método loadView y configuro las restricciones de diseño automático para que sean iguales a la parte superior, posterior, superior e inferior de la supervista de tableview. La supervista es la vista raíz del controlador de vista.

El código de self.navigationController?.pushViewController(notifVC, animated: true) controlador de vista es muy estándar: self.navigationController?.pushViewController(notifVC, animated: true)

El mismo código proporciona un comportamiento normal en iOS 10.

¿Podría por favor señalarme en dirección a lo que está mal?

EDITAR: He creado un controlador de vista de tabla muy simple y puedo reproducir el mismo comportamiento allí. Código:

class VerySimpleTableViewController : UITableViewController { override func viewDidLoad() { super.viewDidLoad() self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell") } override func numberOfSections(in tableView: UITableView) -> Int { return 1 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 4 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel?.text = String(indexPath.row) cell.accessoryType = .disclosureIndicator return cell } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) let vc = VerySimpleTableViewController.init(style: .grouped) self.navigationController?.pushViewController(vc, animated: true) } }

EDIT 2: pude limitar el problema a mi personalización de UINavigationBar. Tengo una personalización como esta:

rootNavController.navigationBar.setBackgroundImage(createFilledImage(withColor: .white, size: 1), for: .default)

donde createFilledImage crea una imagen cuadrada con un tamaño y color determinados.

Si comento esta línea, recupero el comportamiento normal.

Agradecería cualquier idea sobre este asunto.


Además de la respuesta de maggy

C OBJETIVO

if (@available(iOS 11.0, *)) { scrollViewForView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; }

Este problema fue causado por un error en iOS 11 donde los safeAreaInsets de la vista del controlador de vista se configuraron incorrectamente durante la transición de navegación, que debería corregirse en iOS 11.2. Establecer contentInsetAdjustmentBehavior en .never no es una gran solución porque probablemente tendrá otros efectos secundarios indeseables. Si utiliza una solución alternativa, asegúrese de eliminarla para las versiones de iOS> = 11.2

mencionado por smileyborg (ingeniero de software en Apple)


Además, si usa la barra de pestañas, el contenido del contenido inferior de la vista de colección será cero. Para esto, ponga el siguiente código en viewDidAppear:

if #available(iOS 11, *) { tableView.contentInset = self.collectionView.safeAreaInsets }


Así es como me las arreglé para solucionar este problema mientras permitía que iOS 11 configurara las inserciones automáticamente . Estoy usando UITableViewController .

  • Seleccione "Extender bordes debajo de las barras superiores" y "Extender bordes debajo de las barras opacas" en su controlador de vista en el guión gráfico (o mediante programmatically ). Las inserciones de área segura evitarán que su vista pase por debajo de la barra superior.
  • Marque el botón "Inserciones en el área segura" en la vista de su tabla en su guión gráfico. (o tableView.insetsContentViewsToSafeArea = true ) - Esto podría no ser necesario, pero es lo que hice.
  • Establezca el comportamiento de ajuste de inserción de contenido en "Ejes desplazables" (o tableView.contentInsetAdjustmentBehavior = .scrollableAxes ). .always podría funcionar, pero no lo .always .

Otra cosa para probar si todo lo demás falla:

UIViewController método viewSafeAreaInsetsDidChange UIViewController para obtener la vista de tabla para forzar el ajuste de las inserciones de la vista de desplazamiento a las inserciones de área segura. Esto está en conjunción con el ajuste ''Nunca'' en la respuesta de Maggy.

- (void)viewSafeAreaInsetsDidChange { [super viewSafeAreaInsetsDidChange]; self.tableView.contentInset = self.view.safeAreaInsets; }

Nota: self.tableView y self.view deberían ser lo mismo para UITableViewController


Eliminar espacio adicional en la parte superior de collectionView o tableView

if #available(iOS 11.0, *) { collectionView.contentInsetAdjustmentBehavior = .never //tableView.contentInsetAdjustmentBehavior = .never } else { automaticallyAdjustsScrollViewInsets = false }

El código anterior collectionView o tableView va debajo de la barra de navegación.
El siguiente código evita que la vista de colección vaya debajo de la navegación

self.edgesForExtendedLayout = UIRectEdge.bottom

pero me encanta usar la lógica y el código a continuación para UICollectionView

Los valores de inserción de borde se aplican a un rectángulo para reducir o expandir el área representada por ese rectángulo. Normalmente, las inserciones de borde se utilizan durante el diseño de la vista para modificar el marco de la vista. Los valores positivos hacen que el marco se inserte (o reduzca) en la cantidad especificada. Los valores negativos hacen que el marco se comience (o expanda) en la cantidad especificada.

collectionView.contentInset = UIEdgeInsets(top: -30, left: 0, bottom: 0, right: 0) //tableView.contentInset = UIEdgeInsets(top: -30, left: 0, bottom: 0, right: 0)

La mejor manera para UICollectionView

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { return UIEdgeInsets(top: -30, left: 0, bottom: 0, right: 0) }


Eliminar este código funciona para mí

self.edgesForExtendedLayout = UIRectEdgeNone


En mi caso esto funcionó (ponerlo en viewDidLoad):

self.navigationController.navigationBar.translucent = YES;


Esto parece más un error que un comportamiento previsto. Ocurre cuando la barra de navegación no es translúcida o cuando se configura la imagen de fondo.

Si solo configura contentInsetAdjustmentBehavior en .never, las inserciones de contenido no se configurarán correctamente en el iPhone X, por ejemplo, el contenido iría al área inferior, debajo de las barras de desplazamiento.

Es necesario hacer dos cosas:
1. evitar que scrollView se anime en push / pop
2. retenga el comportamiento automático porque es necesario para iPhone X. Sin esto, por ejemplo, en vertical, el contenido irá debajo de la barra de desplazamiento inferior.

Nueva solución simple: en XIB: simplemente agregue una nueva UIView en la parte superior de su vista principal con la parte superior, el inicio y el final a la supervista y la altura establecida en 0. No tiene que conectarlo a otras subvistas ni nada.

Vieja solución:

Nota: Si está utilizando UIScrollView en modo horizontal, aún no establece correctamente las inserciones horizontales (¿otro error?), Por lo que debe fijar el inicio / final de scrollView a safeAreaInsets en IB.

Nota 2: La solución a continuación también tiene el problema de que si tableView se desplaza hacia la parte inferior, y presiona el controlador y vuelve a aparecer, ya no estará en la parte inferior.

override func viewDidLoad() { super.viewDidLoad() // This parts gets rid of animation when pushing if #available(iOS 11, *) { self.tableView.contentInsetAdjustmentBehavior = .never } } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) // This parts gets rid of animation when popping if #available(iOS 11, *) { self.tableView.contentInsetAdjustmentBehavior = .never } } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // This parts sets correct behaviour(insets are correct on iPhone X) if #available(iOS 11, *) { self.tableView.contentInsetAdjustmentBehavior = .automatic } }



Puede editar este comportamiento de una vez en toda la aplicación utilizando NSProxy en, por ejemplo, didFinishLaunchingWithOptions:

if (@available(iOS 11.0, *)) { [UIScrollView appearance].contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; }



asegúrese de agregar el código adicional junto con el código anterior de la siguiente manera. Resolvió el problema

override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) // print(thisUISBTV.adjustedContentInset) }


if #available(iOS 11, *) { self.edgesForExtendedLayout = UIRectEdge.bottom }

Estaba usando UISearchController con resultados personalizados que tienen vista de tabla. Al presionar un nuevo controlador en el controlador de resultados, la vista de tabla se encuentra bajo búsqueda.

El código mencionado anteriormente solucionó totalmente el problema