yes style pwa name icon home content color capable bar apps apple app ios iphone uitableview uiscrollview scroll

ios - style - Manipulación de toques para UIScrollViews anidados que se desplazan en la misma dirección



pwa safari icon (5)

El reconocedor de gestos para la vista de desplazamiento A tendría que pasar al reconocedor de gestos para que la vista de desplazamiento B tenga un movimiento continuo, lo que estoy bastante seguro de que no es posible. ¿Por qué no combinar el contenido de las dos vistas de desplazamiento en su lugar y luego tendría un movimiento continuo? Este código combinará el contenido de scrollView A y B en solo A.

UIScrollView* scrollViewA = ...; UIScrollView* scrollViewB = ...; NSArray* subviews = scrollViewB.subviews; for (int i = 0; i < subviews.count; i++) { UIView* subview = [subviews objectAtIndex:i]; CGRect frame = subview.frame; frame.origin.y += scrollViewA.contentSize.height; subview.frame = frame; [scrollViewA addSubview:subview]; } CGSize size = scrollViewA.contentSize; size.height += scrollViewB.contentSize.height; scrollViewA.contentSize = size;

Tengo dos UIScrollViews anidados, ambos desplazándose en la dirección vertical. Necesito la vista de desplazamiento exterior para desplazarse hasta su rango máximo antes de permitir que la vista de desplazamiento interior se desplace. La vista de desplazamiento interna no debe ser desplazable hasta que la vista de desplazamiento externa haya alcanzado su rango máximo. Aquí hay una ilustración:

En el diagrama de la izquierda, un arrastre vertical dentro de la Scrollview B de Scrollview B debe mover la Scrollview A desplazamiento Scrollview A y la Scrollview B no debe ser desplazable (pero aún así debe poder recibir toques / toques). Una vez que Scrollview A alcanza su rango máximo (cuando Scrollview B llega a la parte superior de la pantalla), Scrollview B debe desplazarse. Esto necesita trabajar en un movimiento continuo.

He intentado alternar ScrollView B ''s scrollEnabled desde ScrollView A ''s scrollViewDidScroll: método delegado, pero esto no parece ser una solución viable porque no funciona en un movimiento continuo (por ejemplo: el usuario debe liberar y vuelva a tocar después de que Scrollview B llegue a la parte superior de la pantalla).

¿Cuál es la mejor manera de implementar esto de manera que funcione en un movimiento continuo?


El requisito de que esto funcione en un movimiento continuo indica la respuesta: debe usar solo un UIScrollView, no dos.

Si solo tiene una vista de desplazamiento, puede realizar su magia anulando el método layoutSubviews de layoutSubviews y resaltando su contenido para realizar su efecto de paralaje basado en el valor actual de contentOffset . Asegúrese de que contentSize siempre refleje la altura completa (incluso puede actualizar contentSize dentro de layoutSubviews si es necesario).

Para una arquitectura, tome su diagrama existente y simplemente reemplace Scrollview B con View B.


En mi caso, resolví la subclasificación de UIScrollView para el ScrollView externo.

class MYOuterScrollView: UIScrollView, UIGestureRecognizerDelegate { override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool { return true } func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true } }


Resolví el problema de la siguiente manera. No estoy realmente contento con eso ya que me parece demasiado complicado, pero funciona (tenga en cuenta que el código a continuación es una versión simplificada y no probada de mi código, que se debe a una interfaz de usuario diferente más complicada):

Tengo 3 propiedades que controlan el desplazamiento:

@property (nonatomic, assign) CGFloat currentPanY; @property (nonatomic, assign) BOOL scrollA; @property (nonatomic, assign) BOOL scrollB;

Desplazamiento en 2 pasos:

Deshabilite el desplazamiento para B y habilite el desplazamiento para A.
Esto permite desplazar A.

Cuando A alcanza su posición máxima, deshabilite el desplazamiento para A y habilite el desplazamiento para B:

-(void)scrollViewDidScroll: (UIScrollView *)scrollView { if (scrollView.contentOffset.y >= self.maxScrollUpOffset) { [scrollView setContentOffset:CGPointMake(0, self.maxScrollUpOffset) animated:NO]; self.scrollviewA.scrollEnabled = NO; self.scrollviewB.scrollEnabled = YES; self.scrollB = YES; } }

Esto da el siguiente efecto:
Cuando A se desplaza hacia arriba, detendrá el desplazamiento cuando se alcanza su tamaño máximo. Sin embargo, B no iniciará el desplazamiento, ya que el reconocedor de gestos de paneo de A no reenvía sus acciones al reconocedor de gestos de panorámico de B. Por lo tanto, uno tiene que levantar el dedo y comenzar un segundo desplazamiento. Entonces, B se desplazará. Esto da el desplazamiento de 2 pasos.

Desplazamiento continuo:

Para el desplazamiento continuo, B debe desplazarse mientras el dedo que comenzó a desplazarse de A continúa moviéndose hacia arriba. Para detectar esto, agregué un reconocedor de gesto de paneo adicional a A, y lo habilité para detectar gestos simultáneamente con los reconocedores de gestos integrados de A y B:

- (BOOL)gestureRecognizer:(UIPanGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UISwipeGestureRecognizer *)otherGestureRecognizer { return YES; }

En la acción de este reconocedor de gesto de paneo adicional, calculo la distancia que el dedo ha movido hacia arriba una vez que se ha alcanzado el límite de desplazamiento de A. Por esta distancia, B se desplaza programáticamente:

- (void)panGestureRecognizerAction:(UIPanGestureRecognizer *)recognizer { if (recognizer.state != UIGestureRecognizerStateChanged) { self.currentPanY = 0; self.scrollB = NO; self.scrollA = NO; } else { CGPoint currentTranslation = [recognizer translationInView:self.scrollviewA]; CGFloat currentYup = currentTranslation.y; if (self.scrollA || self.scrollB) { if (self.currentPanY == 0) { self.currentPanY = currentYup; } CGFloat additionalYup = self.currentPanY - currentYup; if (self.scrollA) { CGFloat offset = self.scrollviewA.scrollUpOffset + additionalYup; if (offset >= 0) { self.scrollviewA.contentOffset = CGPointMake(0, offset); } else { self.scrollviewA.contentOffset = CGPointZero; } } else if (self.scrollB){ self.scrollviewB.contentOffset = CGPointMake(0, additionalYup); } } } }

Todavía hay una desventaja:
Si comienza a desplazarse, levante el dedo y deje que el scrollView se desacelere, se comportará como el desplazamiento en 2 etapas, ya que el reconocedor de gesto de paneo adicional no reconocerá ningún gesto de paneo.