ios - Configurar contentOffset mediante programación desencadena scrollViewDidScroll
uiscrollview uiscrollviewdelegate (6)
Tengo algunos UIScrollView
en una página. Puede desplazarlos de forma independiente o bloquearlos juntos y desplazarlos como uno solo. El problema ocurre cuando están bloqueados.
Uso UIScrollViewDelegate
y scrollViewDidScroll:
para seguir el movimiento. contentOffset
el contentOffset
de UIScrollView
que cambió y luego contentOffset
el cambio a otras vistas de desplazamiento estableciendo su propiedad contentOffset
para que coincida.
Genial ... excepto que noté muchas llamadas extra. Al cambiar de forma programada el contentOffset
de mis vistas de desplazamiento, se activa el método de delegado scrollViewDidScroll:
para llamar. Intenté usar setContentOffset:animated:
lugar, pero sigo recibiendo el activador del delegado.
¿Cómo puedo modificar mi contentOffsets programmatically para no desencadenar scrollViewDidScroll:
:?
Notas de implementación ... Cada UIScrollView
es parte de una UIView
personalizada que usa un patrón de delegado para devolver la llamada a la subclase UIViewController
que se presenta UIViewController
que se encarga de coordinar los diversos valores de contentOffset
.
¿Qué pasa con el uso de las propiedades existentes de UIScrollView?
if(scrollView.isTracking || scrollView.isDragging || scrollView.isDecelerating) {
//your code
}
Es posible cambiar el desplazamiento de contenido de un UIScrollView
sin desencadenar la devolución de llamada de delegado scrollViewDidScroll:
estableciendo los límites de UIScrollView
con el origen establecido en el desplazamiento de contenido deseado.
CGRect scrollBounds = scrollView.bounds;
scrollBounds.origin = desiredContentOffset;
scrollView.bounds = scrollBounds;
Esta no es una respuesta directa a la pregunta, pero si obtiene lo que parecen ser falsos tales mensajes, TAMBIÉN puede deberse a que está cambiando los límites. Estoy usando un código de ejemplo de Apple con un método "tilePages" que elimina y agrega subvista a una vista de desplazamiento. Esto ocasionalmente da como resultado scrollViewDidScroll adicional: los mensajes se llaman de inmediato, por lo que entra en una recursión que seguramente no esperaba. En mi caso, tuve un desagradable accidente imposible de encontrar.
Lo que terminé haciendo fue poner en cola la llamada en la cola principal:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if(scrollView == yourScrollView) {
// dispatch fixes some recursive call to scrollViewDidScroll in tilePages (related to removeFromSuperView)
// The reason can be found here: http://.com/questions/9418311
dispatch_async(dispatch_get_main_queue(), ^{ [self tilePages]; });
}
}
Otro enfoque es agregar algo de lógica en su delegado scrollViewDidScroll para determinar si el cambio en el desplazamiento de contenido se activó programáticamente o por el toque del usuario.
- Agregue una variable booleana ''isManualScroll'' a su clase.
- Establezca su valor inicial en falso.
- En scrollViewWillBeginDragging, establézcalo en verdadero.
- En su scrollViewDidScroll, compruebe que sea verdadero y solo responda si lo es.
- En scrollViewDidEndDecelerating, establézcalo en falso.
- En scrollViewWillEndDragging agregue lógica para establecerlo en falso si la velocidad es 0 (ya que no se llamará a scrollViewDidEndDecelerating en este caso).
Simplificando la respuesta de @ Tark, puede colocar la vista de desplazamiento sin scrollViewDidScroll
en una línea como esta:
scrollView.bounds.origin = CGPoint(x:0, y:100); // whatever values you''d like
Tratar
id scrollDelegate = scrollView.delegate;
scrollView.delegate = nil;
scrollView.contentOffset = point;
scrollView.delegate = scrollDelegate;
Trabajó para mi.