2011-07-24 11 views
8

Estoy escribiendo una aplicación que tiene una vista de estantería como iBooks.Cómo arrastrar y mover algo y desplazarse al mismo tiempo en UIScrollView

El problema ahora es: Puedo arrastrar y soltar en un libro de lugar para another.But ¿cómo puedo hacer esto sucede al mismo tiempo en que me arrastre libro a la parte inferior de la ScrollView:

  1. hacen que el desplazamiento hacia abajo ScrollView
  2. mantener el libro siguen el dedo
  3. lugar los otros libros en el lugar correcto con la animación como mover aplicaciones en trampolín

sé que hay un AQGridView en Github, pero parece que la demostración del trampolín no admite desplazarse y moverse al mismo tiempo. (Ya configuré scrollEnable en SÍ)

Respuesta

13

Te daré mi solución, pero como todo es bastante grande, Solo te daré los fragmentos relevantes.

Además, tenga en cuenta que utilizo un reconocedor de gestos para el arrastre (UILongPressGestureRecognizer) ya que así es como el usuario inicia el arrastre en mi aplicación, manteniendo su dedo presionado sobre el objeto. Por lo tanto, cada subvista que puede arrastrar tiene su propio UILongPressGestureRecognizer asignado, y el destino/selector de ese reconocedor está en otra clase que administra tanto la vista de desplazamiento como las subvistas.

aquí es el objetivo del reconocedor gesto:

-(void)dragged:(UILongPressGestureRecognizer *)panRecog 
{ 
    if (panRecog.state == UIGestureRecognizerStateBegan) 
    { 
     UIView * pannedView = panRecog.view; 

     dragView = pannedView; 
     dragView.center = [panRecog locationInView:scrollView]; 

     [scrollView bringSubviewToFront:dragView]; 

     [self startDrag]; // Not important, changes some stuff on screen to show the user he is dragging 
     return; 
    } 

    if (panRecog.state == UIGestureRecognizerStateChanged) 
    { 
     int xDelta = dragView.center.x - [panRecog locationInView:scrollView].x; 
     dragView.center = [panRecog locationInView:scrollView]; 

     [self scrollIfNeeded:[panRecog locationInView:scrollView.superview] withDelta:xDelta]; 

     return; 
    } 

    if (panRecog.state == UIGestureRecognizerStateEnded) 
    { 
     [self endDrag]; // Not important, changes some stuff on screen to show the user he is not dragging anymore 
    } 
} 

las cosas que son relevantes para usted:

  • Al iniciar el arrastre almaceno la vista que me arrastre en dragView y establecer su centro para ser la posición de su dedo en relación con la vista de desplazamiento en la que se encuentra.
  • startDrag no es importante para usted, cambia algunas cosas en la pantalla para mostrar al usuario que está arrastrando
  • Cuando realmente movemos nuestro objeto (UIGestureRecognizerStateChanged) obtengo la cantidad de puntos que el usuario movió su dedo y uso ese delta junto con la posición del dedo del usuario para verificar si la vista de desplazamiento debe moverse en scrollSi se necesita.

Este es el código

-(void)scrollIfNeeded:(CGPoint)locationInScrollSuperview withDelta:(int)xDelta 
{ 
    UIView * scrollSuperview = scrollView.superview; 
    CGRect bounds = scrollSuperview.bounds; 
    CGPoint scrollOffset = scrollView.contentOffset; 
    int xOfs = 0; 
    int speed = 10; 

    if ((locationInScrollSuperview.x > bounds.size.width * 0.7) && (xDelta < 0)) 
    { 
     xOfs = speed * locationInScrollSuperview.x/bounds.size.width; 
    } 

    if ((locationInScrollSuperview.x < bounds.size.width * 0.3) && (xDelta > 0)) 
    { 
     xOfs = -speed * (1.0f - locationInScrollSuperview.x/bounds.size.width); 
    } 

    if (xOfs < 0) 
    { 
     if (scrollOffset.x == 0) return; 
     if (xOfs < -scrollOffset.x) xOfs = -scrollOffset.x; 
    } 
    scrollOffset.x += xOfs; 
    CGRect rect = CGRectMake(scrollOffset.x, 0, scrollView.bounds.size.width, scrollView.bounds.size.height); 
    [scrollView scrollRectToVisible:rect animated:NO]; 
    CGPoint center = dragView.center; 
    center.x += xOfs; 
    dragView.center=center; 
} 

Esta cosa sólo el desplazamiento horizontal, vertical, pero el manejo sería bastante similar. Lo que hace es:

  • Compruebe que ha arrastrado en la región límite de la ScrollView (utilizo una frontera 30% a izquierda y derecha como la zona donde el desplazamiento debe suceder). Pero solo si el usuario se movió en esa dirección (xDelta < 0 para izquierda, xDelta> 0 para derecha)
  • siguiente Calculo cuánto mover la vista de desplazamiento, usando una constante de velocidad y escalando esto con qué distancia está el usuario del borde real de la vista de desplazamiento, por lo que la velocidad es proporcional a la distancia al borde del usuario.
  • El último paso es desplazar la vista de desplazamiento con un scrollRectToVisible no animado. Por supuesto, su vista arrastrada se mueve, por lo que compensamos eso con un desplazamiento opuesto de su centro.

Espero que esto pueda ayudarlo.

+0

¡Eso es lo que necesito! Realmente gracias – ultragtx

+0

Bien hecho, gracias;)! – Oliver

+0

¡Esto funciona genial! Sin embargo, su calculo de xDelta debe ser la ubicación actual menos la última ubicación. valor final menos valor inicial, de modo que un usuario positivo xDelta menos arrastrado a la derecha, y xDelta negativo significa que arrastró a la izquierda. pero también funciona a tu manera. :) – ucangetit

Cuestiones relacionadas