iphone - Cómo arrastrar y mover algo y desplazarse al mismo tiempo en UIScrollView
ios aqgridview (1)
Estoy escribiendo una aplicación que tiene una vista de estantería como iBooks.
El problema ahora es: puedo arrastrar y soltar un libro de un lugar a otro. Pero ¿cómo puedo hacer que esto ocurra al mismo tiempo cuando arrastro el libro hasta la parte inferior de la vista de desplazamiento?
- hacer que scrollview se desplace hacia abajo
- mantén el libro siguiendo mi dedo
- coloque los otros libros en el lugar correcto con 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 desplazamiento y movimiento al mismo tiempo. (Ya configuré scrollEnable en YES)
Te daré mi solución, pero como todo es bastante grande, solo te daré los fragmentos relevantes.
Además, tenga en cuenta que uso 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í está el objetivo del reconocedor de gestos:
-(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 ti:
- Al iniciar la función de arrastrar, almaceno la vista que arrastro en dragView y configuro su centro para que sea la posición que su dedo está en relación con la vista de desplazamiento en la que se encuentra.
- startDrag no es importante para ti, cambia algunas cosas en la pantalla para mostrar al usuario que está arrastrando
- Cuando 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;
}
Esto solo hace desplazamiento horizontal, pero el manejo vertical sería bastante similar. Lo que hace es:
- Verifica si arrastraste a la región límite de la vista de desplazamiento (utilizo un borde de 30% hacia la izquierda y hacia la derecha como la zona donde debería ocurrir el desplazamiento). Pero solo si el usuario se movió en esa dirección (xDelta <0 para la izquierda, xDelta> 0 para la derecha)
- A continuación, calculo cuánto mover la vista de desplazamiento, usando una constante de velocidad y escalando esto con qué tan lejos 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 ayudarte.