2011-04-11 21 views
5

Estoy intentando arrastrar una imagen y dejarla volver a su posición original después de soltarla. Hasta el momento, puedo arrastrar una imagen mediante la creación como un botón mediante el siguiente código: (como se ve en la respuesta a esta pregunta: Basic Drag and Drop in iOS)Arrastrar y soltar objetos y devolverlos a su posición original

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; 
[button addTarget:self action:@selector(imageTouch:withEvent:) forControlEvents:UIControlEventTouchDown]; 
[button addTarget:self action:@selector(imageMoved:withEvent:) forControlEvents:UIControlEventTouchDragInside]; 
[button setImage:[UIImage imageNamed:@"vehicle.png"] forState:UIControlStateNormal]; 
[self.view addSubview:button]; 

Y después me defino:

- (IBAction) imageMoved:(id) sender withEvent:(UIEvent *) event 
{ 
    CGPoint point = [[[event allTouches] anyObject] locationInView:self.view]; 
    UIControl *control = sender; 
    control.center = point; 
} 

¿Cómo puedo hacer que regrese a su posición original después de soltarlo? Para empezar, guardaré la posición en la que se supone que debe regresar cada imagen, pero luego, de todos modos, hay que indicar un UIImage para ir desde su posición actual y pasar a ¿otro ?, ¿o alguna otra solución alternativa?

Respuesta

-1

Sabes qué, yo estaba trabajando en esto ayer, por lo que aquí vas con un poco de animación de bonificación:

- (void)previewImageTouchUpInside:(UIButton*)aButton { 
    if (!previewImageDragged) { 
     [self selectPreviewImage:aButton]; 
     return; 
} 

    previewImageDragged = NO; 

    // If user drag photo a little and then release, we'll still treat it as a tap 
    // instead of drag 
    if ((originalPositionOfButton.x - aButton.center.x) * 
     (originalPositionOfButton.x - aButton.center.x) + 
     (originalPositionOfButton.y - aButton.center.y) * 
     (originalPositionOfButton.y - aButton.center.y) < 10) { 
     aButton.center = originalPositionOfButton; 
     [self selectPreviewImage:aButton]; 
     return; 
    } 

    [UIView animateWithDuration:0.5 
     delay:0 
     options:UIViewAnimationOptionCurveEaseOut | 
     UIViewAnimationOptionAllowUserInteraction animations:^{ 
     aButton.center = originalPositionOfButton; 
    } completion:nil]; 
} 



- (void)previewImageDraggedInside:(UIButton*)aButton event:(UIEvent*)event { 
    if (!previewImageDragged) { 
     originalPositionOfButton = aButton.center; 
     [self.view bringSubviewToFront:aButton]; 
     [self.view bringSubviewToFront:[self.view viewWithTag:CHOOSE_PHOTO_BUTTON_TAG]]; 
    } 

    UITouch* touch = [[event allTouches] anyObject]; 

    previewImageDragged = YES; 
    aButton.center = CGPointMake(aButton.center.x+[touch locationInView:self.view].x- 
     [touch previousLocationInView:self.view].x, 
     aButton.center.y+[touch locationInView:self.view].y- 
     [touch previousLocationInView:self.view].y); 
} 

Todavía tiene un par de números mágicos y no he cambiado el nombre de las funciones y variables para adaptarse a su ejemplo, pero debe ser claro. También hice la sangría aquí ya que no rompo manualmente las líneas largas en mi código.

0

¿Qué tal si llama a un selector en UIControlEventTouchUpInside y luego en el selector, simplemente ajuste el marco de su botón en una nueva coordenada xey (las que ha guardado).

+0

Gracias. Pero eso movería el UIButton a una nueva posición al instante, ¿no?Si es así, es posible indicarle a UIButton que se mueva de su posición actual a la nueva una vez que se llame al selector de UIControlEventTouchUpInside. –

+0

Lea los documentos para "animación" –

7

UIGestureRecognizer es recomendado por Apple para iOS recientes. Puede usarlo no solo para UIButton, sino también para UIView (especialmente UIImageView en su caso), etc. Así que me gustaría recomendarlo.

En la interfaz:

@interface TestDragViewController : UIViewController { 
    IBOutlet UIImageView *dragImage; 
    CGPoint originalCenter; 
} 

En viewDidLoad, PLZ recuerda que permita userInteraction:

- (void)viewDidLoad { 
    [super viewDidLoad]; 


    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self 
                       action:@selector(dragGesture:)]; 
    [dragImage addGestureRecognizer:panGesture]; 
    [dragImage setUserInteractionEnabled:YES]; 
} 

Y en su selector, que acaba de establecer la animación para visualizar el efecto de volver:

#pragma mark - 
#pragma mark UIPanGestureRecognizer selector 
- (void) dragGesture:(UIPanGestureRecognizer *) panGesture{ 
    CGPoint translation = [panGesture translationInView:self.view]; 

    switch (panGesture.state) { 
     case UIGestureRecognizerStateBegan:{ 
      originalCenter = dragImage.center; 
     } 
      break; 
     case UIGestureRecognizerStateChanged:{ 
      dragImage.center = CGPointMake(dragImage.center.x + translation.x, 
              dragImage.center.y + translation.y); 
     } 
      break; 
     case UIGestureRecognizerStateEnded:{    
      [UIView animateWithDuration:kImageReturnTime 
          animations:^{ 
           dragImage.center = originalCenter; 
          } 
          completion:^(BOOL finished){ 
           NSLog(@"Returned"); 
          }]; 
     } 
      break; 
     default: 
      break; 
    } 

    [panGesture setTranslation:CGPointZero inView:self.view]; 
} 

Cheers,

Tommy

+0

de lejos, esta es la solución correcta, sin complejidades o sin crear abstracciones innecesarias !, ¡bien hecho, Tommy! – Wilson

0

En la solución a la que he vinculado he creado un gestor genérico de arrastre que se encarga de devolver un objeto arrastrado a la posición original (si se lanza fuera de una zona de caída conocida). Actualmente no hay animación en la solución, pero podría combinar algunas de las ideas presentadas anteriormente.

Véase la de alguna forma generic drag and drop solution in iOS

1

Definir CGPoint A nivel mundial, o en el archivo .h.

CGPoint point;   

     UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; 
     [button addTarget:self action:@selector(imageTouch:withEvent:)forControlEvents:UIControlEventTouchDown]; 
     [button addTarget:self action:@selector(imageMoved:withEvent:) forControlEvents:UIControlEventTouchDragInside]; 
     [button setImage:[UIImage imageNamed:@"vehicle.png"] forState:UIControlStateNormal]; 
     [self.view addSubview:button]; 

Y después me defino:

- (IBAction) imageMoved:(UIButton*) sender withEvent:(UIEvent *) event 
{ 
point = [[[event allTouches] anyObject] locationInView:self.view]; 
UIControl *control = sender; 
control.center = point; 
[sender addTarget:self action:@selector(touches:withEvent:) forControlEvents:UIControlEventTouchUpInside]; 
} 

-(void)touches:(UIButton *)button withEvent:(UIEvent *)event { 

[UIView animateWithDuration:0.1 delay:0 options:UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionAllowUserInteraction animations:^{ 
    button.center = point; 

} completion:^(BOOL finished){ 
    if (finished) { 
    // do anything yu want 
    } 

funciona causa increíble lo estoy usando en mi proyecto!