El offset de contenido de UIScrollView se reinicia

He estado luchando durante mucho time con un problema con un UIScrollView.

Tengo un UIScrollVIew que contiene un UITextView como subvista. Cuando selecciono la vista de text, aparece un keyboard. Quiero cambiar el tamaño de la vista de text para que se ajuste exactamente al espacio disponible, y también desplazar la vista de desplazamiento para que la vista de text se ubique exactamente en el espacio visible (no oculta por el keyboard).

Cuando aparece el keyboard, invoco un método que calcula el tamaño apropiado para la vista de text y luego realiza el siguiente código:

 [UIView animateWithDuration:0.3 animations:^ { self.textView.frame = frame; } ]; [self.scrollView setContentOffset:CGPointMake(0,frame.origin.y) animated:YES]; 

(aquí, el marco es el marco apropiado para la vista de text).

Lamentablemente, la vista de desplazamiento no siempre se desplaza a la position correcta, especialmente cuando ya está en un desplazamiento de contenido vertical no cero cuando selecciono la vista de text. Sé que la compensación de contenido a la que la estoy configurando es correcta.

Después de muchas testings, finalmente me di count de que lo que estaba sucediendo era que después de completar la animation, la vista de desplazamiento volvía a desplazarse automáticamente.

Este código funciona:

 UIView animateWithDuration:0.3 animations:^ { self.textView.frame = frame; } completion:^(BOOL finished) { [self.scrollView setContentOffset:CGPointMake(0, frame.origin.y) animated:YES]; } ]; 

pero parece extraño porque la vista de desplazamiento se desplaza a la position incorrecta, luego a la derecha.

¿Alguien sabe cómo puedo evitar que la vista de desplazamiento cambie su compensación de contenido cuando el marco de vista de text termina su animation?

Estoy probando con iOS 5.0.


Aquí hay una solución que encontré que funciona. Todavía no entiendo completamente lo que está sucediendo, es posible que tenga algo que ver con la forma en que se establecen mis muelles y puntales. Básicamente estoy networkinguciendo el tamaño del contenido de la vista de desplazamiento en la misma cantidad en que la vista de text se networkinguce.

 - (void)keyboardDidShow:(NSNotification*)aNotification { NSDictionary* info = [aNotification userInfo]; // Get the height of the keyboard CGRect kbRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue]; kbRect = [self.view convertRect:kbRect fromView:nil]; CGSize kbSize = kbRect.size; // Adjust the height of the text view to fit in the visible view CGRect frame = self.textView.frame; int visibleHeight = self.view.frame.size.height; visibleHeight -= kbSize.height; frame.size.height = visibleHeight; // Get the new scroll view content size CGSize contentSize = self.scrollView.contentSize; contentSize.height = contentSize.height - self.textView.frame.size.height + frame.size.height; [UIView animateWithDuration:0.1 animations:^ { self.textView.frame = frame; // Note that the scroll view content size needs to be reset, or the scroll view // may automatically scroll to a new position after the animation is complete. self.scrollView.contentSize = contentSize; [self.scrollView setContentOffset:CGPointMake(0, frame.origin.y) animated:YES]; } ]; // Turn off scrolling in scroll view self.scrollView.scrollEnabled = NO; } // Called when the UIKeyboardWillHideNotification is sent - (void)keyboardWillBeHidden:(NSNotification*)aNotification { // Update the view layout [UIView animateWithDuration:0.3 animations:^ { self.scrollView.contentOffset = CGPointZero; [self updateViewLayout]; } ]; // Turn on scrolling in the scroll view self.scrollView.scrollEnabled = YES; } 

( [self updateViewLayout] es un método que devuelve la vista de text a la altura correcta y restablece el tamaño del contenido de la vista de desplazamiento, así como asegurarse de que todas las demás subvistas estén correctamente posicionadas).

No ajuste el marco de la vista de text. Todo lo que necesita hacer es desplazarse por la vista de desplazamiento. Si desplaza la vista de desplazamiento animada, la textView se deslizará animada. Simplemente haga lo siguiente:

 [self.scrollView setContentOffset:CGPointMake(0, frame.origin.y) animated:YES]; 

Si necesita la vista de desplazamiento para desplazarse a una velocidad específica, ajuste manualmente el desplazamiento de contenido en un bloque de animation (no lo he probado, puede ajustar el indicador de animation o recorrer el desplazamiento de contenido de un píxel en un time si esto no funciona)

 [UIView animateWithDuration:0.3f animations:^{ [self.scrollView setContentOffset:CGPointMake(0, frame.origin.y) animated:YES]; } ]; 

Creo que también tuve algo similar. Quería que mi UIScrollView horizontal volviera a su desplazamiento original (0,0), y cada vez que volvía a animarlo, estaría a solo un par de píxeles, pero tan pronto como alguien tocara la vista de desplazamiento, continuaría y terminaría La animation (casi como retraso en un videojuego).

Debido a eso, intenté ponerlo en GCD como la queue principal y funcionó perfectamente después de eso. Aquí está el código:

 - (void)setPageZero{ dispatch_async(dispatch_get_main_queue(), ^{ [UIView animateWithDuration:1.0f delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ [self.scrollView setContentOffset:CGPointMake(0, self.scrollView.frame.origin.y) animated:YES]; } completion:^(BOOL finished) {}]; }); } 

Lo que básicamente hace, es que pone la animation en la queue principal (¡como una supercarretera en la CPU / GPU) y la prioriza sobre otras cosas!

Espero que esto ayude a futuros lectores.

Estoy teniendo un problema similar. Básicamente tengo una vista de desplazamiento con tres páginas cada una con una class UIView personalizada. La class UIView personalizada contiene una image y una cantidad de vistas superpuestas que contienen información sobre la image. Las vistas de superposition contienen una cantidad de campos de UITextView .

Adjunto las vistas personalizadas a la vista de desplazamiento y luego cargo la image y las superposiciones usando operaciones de bloque. Deslizo hacia la derecha borrando la primera vista, reposicionando las dos vistas siguientes y agregando una nueva vista a la derecha.

Si creo los objects UITextField y deshabilito el desplazamiento de la siguiente manera:

 UITextView* view = [[UITextView alloc] initWithFrame:CGRectMake(position.x,position.y,width,height)]; view.editable = NO; view.scrollEnabled = NO; 

Luego, la vista de desplazamiento se vuelve a colocar entre páginas cuando return del código de bloque. Tenga en count que no cambio la position de la vista de desplazamiento y al salir del bloque, la vista de desplazamiento está en la position correcta.

Sin embargo, si comento el código para deshabilitar el desplazamiento

 UITextView* view = [[UITextView alloc] initWithFrame:CGRectMake(position.x,position.y,width,height)]; view.editable = NO; // view.scrollEnabled = NO; 

este reposicionamiento no ocurre y el desplazamiento funciona como se esperaba.

Completa piratería: puede mejorar el problema de reinicio:

 - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { [self setContentOffset:self.contentOffset animated:NO]; }