2011-06-29 15 views
34

estoy ajustando el estado de un controlador de vista de detalle, justo antes de que se empuja en una navigationController:UIScrollView ajusta contentOffset cuando cambia contentSize

[self.detailViewController detailsForObject:someObject]; 
[self.navigationController pushViewController:self.detailViewController 
            animated:YES]; 

En el DetailViewController un ScrollView reside. ¿Qué puedo cambiar el tamaño de contenido basada en el objeto pasado:

- (void)detailsForObject:(id)someObject { 
    // set some textView's content here 
    self.contentView.frame = <rect with new calculated size>; 

    self.scrollView.contentSize = self.contentView.frame.size; 
    self.scrollView.contentOffset = CGPointZero; 
} 

Ahora, todo esto funciona, pero el ScrollView ajusta es contentOffset durante el navigationController deslizable en la animación. El contentOffset se establecerá en la diferencia entre el último contentSize y el nuevo calculado. Esto significa que la segunda vez que abra detailsView, los detalles se desplazarán a alguna ubicación no deseada. Aunque configuro el contentOffset en CGPointZero explícitamente.

Encontré que restablecer el contentOffset en - viewWillAppear no tiene ningún efecto. Lo mejor que podía llegar a está restableciendo la contentOffset en viewDidAppear, causando una notable movimiento ascendente y descendente del contenido:

- (void)viewDidAppear:(BOOL)animated { 
    self.scrollView.contentOffset = CGPointZero; 
} 

¿Hay una manera de prevenir una UIScrollView de ajustar su contentOffset cuando su contentSize se cambia?

+0

¿Por qué está ajustando el desplazamiento de contenido dentro de un bloque de animación? Omita las cosas de CATransaction, por lo que no se anima. Entonces no se verá entrecortado. – Andrew

+0

Eliminar las cosas de CATransaction en realidad no cambia nada, por lo que se elimina. – Berik

+0

¿Estás seguro de que se llama a viewDidAppear? Establecí un punto de interrupción o una declaración NSLog en él. Además, ¿ha intentado cambiar el orden de sus llamadas, es decir, establecer los detalles para Objeto después de presionar? – Andrew

Respuesta

57

Se produce cuando empujando un UIViewController que contiene un UIScrollView usando un UINavigationController.

iOS 7

solución al 1 (Código)

Establecer @property(nonatomic, assign) BOOL automaticallyAdjustsScrollViewInsets-NO.

Solución 2 (Storyboard)

Desactive la Adjust Scroll View Insets

Adjust Scroll View Insets

iOS 6

Solution (Código)

Establezca la propiedad UIScrollViewcontentOffset y contentInset en viewWillLayoutSubviews. Código de muestra:

- (void)viewWillLayoutSubviews{ 
    [super viewWillLayoutSubviews]; 
    self.scrollView.contentOffset = CGPointZero; 
    self.scrollView.contentInset = UIEdgeInsetsZero; 
} 
+1

Esta es una nueva forma de resolver el problema. Es más limpio luego de restablecer el tamaño del contenido. – Berik

+3

Excelente respuesta. Gracias por publicar las diferencias en iOS 7 e incluso incluir las imágenes para aclarar. ¡Súper! – Marchy

+4

GRACIAS! he estado volviendo loco por esto en las últimas dos horas – user2527666

0

¿Es su desplazamientoVer la vista raíz del DetailViewController? En caso afirmativo, intente ajustar el scrollView en un simple UIView y haga de este último la vista raíz de DetailViewController. Como UIView s no tienen una propiedad contentOffset, son inmunes a los ajustes de compensación de contenido realizados por el controlador de navegación (debido a la barra de navegación, etc.).

+1

El scrollView no es la vista raíz del DetailViewController. self.scrollView está vinculado a un UIScrollView que reside en la vista raíz de DetailViewController. – Berik

14

La causa de este problema sigue sin estar clara, aunque he encontrado una solución. Al restaurar el tamaño del contenido y el desplazamiento antes de ajustar ellos, el UIScrollView no se animará:

- (void)detailsForObject:(id)someObject { 
    // These 2 lines solve the issue: 
    self.scrollView.contentSize = CGSizeZero; 
    self.scrollView.contentOffset = CGPointZero; 

    // set some textView's content here 
    self.contentView.frame = <rect with new calculated size>; 

    self.scrollView.contentSize = self.contentView.frame.size; 
    self.scrollView.contentOffset = CGPointZero; 
} 
0

que experimentaron el problema, y ​​para un caso específico - No ajusto el tamaño - He utilizado el siguiente:

float position = 100.0;//for example 

SmallScroll.center = CGPointMake(position + SmallScroll.frame.size.width/2.0, SmallScroll.center.y); 

mismo sería trabajar con y: anotherPosition + SmallScroll.frame.size.height/2.0

Así que si usted no necesita cambiar el tamaño, esta es una solución rápida y sin dolor.

2

Tuve el mismo problema con un UIScrollview, donde el problema fue causado por no configurar el contentSize. Después de configurar el contentSize para la cantidad de elementos, se resolvió este problema.

self.headerScrollView.mainScrollview.contentSize = CGSizeMake(320 * self.sortedMaterial.count, 0); 
Cuestiones relacionadas