2009-09-29 22 views
20

Por lo tanto, UITableView es compatible con el desplazamiento esencialmente "infinito". Puede haber un límite, pero ese imbécil puede desplazarse por un tiempo looonnnggg. Me gustaría imitar este comportamiento con un UIScrollView pero hay dos obstáculos fundamentales:UIScrollView. ¿Alguna idea sobre la implementación de desplazamiento/zoom "infinito"?

1) scrollView.contentSize se fija en el momento de la creación. 2) el acercamiento puede hacer volar cualquier esquema de carga lenta al infierno, ya que puede causar una explosión de datos.

Tiene otros por ahí reflexionado sobre esta idea? Yah, lo sé, básicamente estamos hablando de volver a crear Google Maps aquí. Cualquier idea sería muy apreciada.

Saludos, Doug

+0

¿Has mirado a MapKit? –

+0

bien UITableView es una subclase de UIScrollView –

Respuesta

10

Si bien es imposible tener una UIScrollView verdaderamente infinita, hay algunos trucos simples que usted puede utilizar para emular ese comportamiento.

  1. Manejo de la contentSize fija: tiene algunas vistas de tamaño fijo a cargo de su punto de vista de desplazamiento, y en el lanzamiento o de instancias, defina el contenido de desplazamiento de modo que usted está viendo la mitad de la vista manejado. Entonces simplemente ver el contenido de desplazamiento (utilizando MVA o algún otro método), y si cerca de cualquier borde, actualizar el contenido de la vista con un nuevo conjunto de contenidos (compensado adecuadamente) y restablecer la propiedad del punto de vista de desplazamiento contentOffset de estar de vuelta en el medio.
  2. Manejo de zoom: hacer algo similar, sólo que esta vez ver el factor de zoom en la vista de desplazamiento. Siempre que llegue a cierto punto, realice alguna manipulación con los datos que esté presentando para que aparezca ampliada, luego reinicie el factor de zoom a 1.0. Por ejemplo, si está desplazando una imagen y obtiene el zoom para que aparezca el doble de grande, aplique mediante programación algún tipo de transformación para que la imagen sea dos veces más grande, luego restablezca el factor de zoom de la vista de desplazamiento en 1.0. La imagen seguirá apareciendo ampliada, pero la vista de desplazamiento podrá continuar acercándose más si es necesario. (Google Maps va un paso más allá donde hace perezoso-cargas vistas más detalladas como el usuario acerque - que puede o no puede elegir implementar esto.)
+2

Aquí hay un enlace http://iphonedevelopment.blogspot.com/2009/02/kvo-and-iphone-sdk.html explicando KVO para cualquier persona que no sepa de qué se trata. Como yo no. – Grumdrig

+4

El problema con esta solución es que 'setContentOffset' cancela todo desplazamiento y el movimiento se detiene repentinamente. No conozco una forma de determinar la velocidad a la que se mueve la vista, o cómo reiniciar ese movimiento si lo hiciera. – Grumdrig

+0

¿Pero por qué molestarse en cambiar la compensación de contenido en absoluto? Deja que se desplace, solo asegúrate de mantener el ritmo y mover las vistas de la imagen para que coincidan con lo que el usuario está viendo. –

0

Tal vez el establecimiento de contentSize a algún valor gigantesca y luego mover una limitada número de vistas subyacentes para seguir la posición de vista como en la muestra de mosaico hará el truco.

Para mitigar la posibilidad de eventualmente llegar a un borde y tener que volver a centrar abruptamente la vista (que cancela cualquier desplazamiento actualmente en movimiento), la vista puede volverse cuando está estacionaria, de vez en cuando.

De todos modos, eso es lo que voy a tratar.

+0

Esto parece funcionar bien, FYI. Estoy usando 4 vistas contenidas del mismo tamaño que la vista que contiene, que marchan junto con el desplazamiento. He basado mi código en la (mitad superior de) Muestra de desplazamiento. – Grumdrig

+0

El proyecto de ejemplo oficial de desplazamiento infinito de Apple sugiere usar este método. – zakdances

13

Acabo de terminar la ejecución del desplazamiento infitine para mí. En mi implementación tengo UITableViewCell con un scrollView y botones de navegación. El scrollView contiene x vistas todas con el mismo ancho. las vistas se alinean horizontalmente y la paginación está habilitada.

scrollView.clipsToBounds = YES; 
scrollView.scrollEnabled = YES; 
scrollView.pagingEnabled = YES; 
scrollView.showsHorizontalScrollIndicator = NO; 

Mi codelogic es como la siguiente:

  1. En mi función de inicialización que
    • crear todas las vistas (para el ScrollView) y
    • los pusieron en una matriz y
    • agrégalos al scrollView
  2. Luego invoco una función que calcula en un bucle las posiciones de cada vista (cada vez que detecte un desplazamiento, también deberá llamar a esta función). Siempre toma el primer elemento de la matriz y establece el marco en (0,0, ..., ...), el segundo con (i * ancho, 0, ...., ....) y así en. La función beeing llamada es el siguiente:

    - (void)updateOffsetsOfViews{ 
        int xpos = 0; 
        for (int i=0; i<[views count]; i++) { 
         UIImageView *_view = [views objectAtIndex:i]; 
         CGRect aFrame = _view.frame; 
         aFrame.origin.x = xpos; 
         aFrame.origin.y = 0.0; 
         _view.frame = aFrame; 
         xpos += viewWidth; 
        } 
        float center = 0; 
        if(fmod([views count],2) == 1){ 
         center = viewWidth * ([views count]-1)/2; 
        }else { 
         center = viewWidth * [views count]/2; 
        } 
        [scrollView setContentOffset:CGPointMake(center, 0)]; 
        lastOffset = center; 
    } 
    
  3. Entonces (todavía en el proceso de inicialización) agrego un observador

    [scrollView addObserver:self forKeyPath:@"contentOffset" options:0 context:nil]; 
    

    por lo que cada vez que algo en los cambios ScrollView me sale el (observeValueForKeyPath) - función llamada, que se ve así:

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
    { 
        UIImageView *_viewFirst = (UIImageView *)[views objectAtIndex:0]; 
        if (fmod([scrollView contentOffset].x,viewWidth) == 0.0) { 
         if ([scrollView contentOffset].x > lastOffset) { 
          [views removeObjectAtIndex:0]; 
          [views addObject:_viewFirst];     
          [self updateOffsetsOfViews];  
         }else if ([scrollView contentOffset].x < lastOffset) { 
          UIImageView *_viewLast = (UIImageView *)[views lastObject]; 
          [views removeLastObject]; 
          [views insertObject:_viewLast atIndex:0];    
          [self updateOffsetsOfViews]; 
         } 
        } 
    } 
    
  4. Y en dealloc o viewDidUnload (depende de cómo ponerlo en práctica) no se olvide de remo ve el observador.

    [scrollView removeObserver:self forKeyPath:@"contentOffset"]; 
    

Espero que esto ayude, puede notar algo de sobrecarga, pero en mi aplicación también admite como desplazarse 5 páginas (así ... sin límite) a la vez y autoanimated desplazamiento etc por lo que podría ver algo eso podría ser desechado.

+1

Una solución bastante buena, pero no hagas comparaciones de coma flotante con ==, se romperá. –

+0

Probé tu código.Pero cuando desplazo rápidamente 2 páginas, el código no lo manejará correctamente. – jeswang

2

Tenga en cuenta que cuando el desplazamiento está animado, contentOffset cambia muchas veces, no solo página por página, sino con cada paso de la animación.

Cuestiones relacionadas