2012-01-04 9 views
5

Estoy trabajando en un D & D en un UISplitViewController (basado en el proyecto de plantilla de Xcode), desde el MasterViewController al DetailViewController.iOS (iPad) Arrastrar y colocar en un UISplitViewController

Básicamente, lo que estoy haciendo es crear un UILongPressGestureRecognizer y colocarlo en la propiedad self.tableview de MasterViewController.

A continuación se muestra mi gestor de gestos.

- (void)gestureHandler:(UIGestureRecognizer*)gesture 
{ 
    CGPoint location; 
    NSIndexPath* indexPath = [self.tableView indexPathForRowAtPoint:[gesture locationInView:self.tableView]]; 
    if (gesture.state == UIGestureRecognizerStateBegan) { 
     // Create draggable view 
     NSString* imageCanvasName = [self imageNameByIndexPath:indexPath isDetail:YES]; 
     UIImage* imageCanvas = [UIImage imageNamed:imageCanvasName]; 
     _draggedView = [[UIImageView alloc] initWithImage:imageCanvas]; 

     // Create drag-feedback window, add the drag-view and make the drag-window visible 
     CGRect windowFrame = self.view.window.frame; 
     _dragFeedbackWindow = [[UIWindow alloc] initWithFrame:windowFrame]; 
     location = [gesture locationInView:gesture.view.window]; 
     [_draggedView setCenter:location]; 
     [_dragFeedbackWindow addSubview:_draggedView]; 
     [_dragFeedbackWindow setHidden:NO];  
    } 
    else if (gesture.state == UIGestureRecognizerStateChanged) { 
     // Update drag-view location 
     location = [gesture locationInView:gesture.view.window]; 
     [_draggedView setCenter:location]; 
    } 
    else if (gesture.state == UIGestureRecognizerStateEnded) 
    { 
     // Disconnect drag-view and hide drag-feedback window 
     [_draggedView removeFromSuperview];  
     [_dragFeedbackWindow setHidden:YES]; 

     // If drop is in a valid location... 
     if ([self.tableView pointInside:_draggedView.center withEvent:nil] == NO) 
     { 
      // Get final location in detailViewController coordinates 
      location = [gesture locationInView:self.detailViewController.view]; 
      [_draggedView setCenter:location]; 
      [self.detailViewController.view addSubview:_draggedView]; 
     } 
    } 
    else { 
     NSLog(@"%s unrecognized gesture %d", __FUNCTION__, gesture.state); 
    } 
} 

Todo funciona muy bien cuando el iPad está en modo vertical - el arrastre, la caída - funciona.

Mi problema se inicia si se rota el iPad ... En tal caso, mi _draggedView aparece "contrarrotado" - "reflejará" la rotación del iPad - hasta que se caiga.

Es como debo aplicar un poco de rotación para _dragFeedbackWindow - pero intentado una serie de cosas, en su defecto ...

Alguna idea?

Gracias!

Respuesta

4

bien - me di cuenta de los "por qué" esto sucede, y el "cómo" para fijar (y adjuntar el código del controlador para hacer esto correctamente, todas por debajo de

Aquí está el código ... "Justo. "añadirlo a su MasterViewController (si - como yo - que desea arrastrar desde el maestro a los detalles ...)

// A simple UIView extension to rotate it to a given orientation 
@interface UIView(oriented) 
- (void)rotateToOrientation:(UIInterfaceOrientation)orientation; 
@end 

@implementation UIView(oriented) 
- (void)rotateToOrientation:(UIInterfaceOrientation)orientation { 
    CGFloat angle = 0.0;  
    switch (orientation) { 
     case UIInterfaceOrientationPortraitUpsideDown: 
      angle = M_PI; 
      break; 
     case UIInterfaceOrientationLandscapeLeft: 
      angle = - M_PI/2.0f; 
      break; 
     case UIInterfaceOrientationLandscapeRight: 
      angle = M_PI/2.0f; 
      break; 
     default: // as UIInterfaceOrientationPortrait 
      angle = 0.0; 
      break; 
    } 

    self.transform = CGAffineTransformMakeRotation(angle); 
} 

Ahora, el manejador LongPress gesto ...

- (void)gestureHandler:(UIGestureRecognizer*)gesture 
{ 
    CGPoint location; 
    UIWindow* dragFeedback = [UIApplication sharedApplication].delegate.window; 
    if (gesture.state == UIGestureRecognizerStateBegan) { 
     // Create draggable view 
     _draggedView = [[UIImageView alloc] initWithImage:@"someImage.png"]; 

     // Required to adapt orientation... WORKS, BUT WHY NEEDED??? 
     [_draggedView rotateToOrientation:[[UIApplication sharedApplication] statusBarOrientation]]; 

     // Create drag-feedback window, add the drag-view and make the drag-window visible 
     location = [gesture locationInView:dragFeedback]; 
     [_draggedView setCenter:location]; 
     [dragFeedback addSubview:_draggedView]; 
    } 
    else if (gesture.state == UIGestureRecognizerStateChanged) { 
     // Update drag-view location 
     location = [gesture locationInView:dragFeedback]; 
     [_draggedView setCenter:location]; 
    } 
    else if (gesture.state == UIGestureRecognizerStateEnded) 
    { 
     // Disconnect drag-view and hide drag-feedback window 
     [_draggedView removeFromSuperview];  

     // Get final location in detailViewController coordinates 
     location = [gesture locationInView:self.detailViewController.view]; 
     [_draggedView setCenter:location]; 
     // "Noramlize" orientation... WORKS, BUT WHY NEEDED??? 
     [_draggedView rotateToOrientation:UIInterfaceOrientationPortrait]; 
     [self.detailViewController.view addSubview:_draggedView]; 
    } 
    else { 
     NSLog(@"%s unrecognized gesture %d", __FUNCTION__, gesture.state); 
    } 
} 

Este Funciona de maravilla - déjame saber cómo funciona para ti (si necesitas un proyecto de muestra, házmelo saber ...)

+0

Hola Reuven, tengo los mismos requisitos. ¿Podría compartir un proyecto de muestra? Gracias. – applefreak

+0

seguro. me tomará un día para la limpieza. – Reuven

+1

Aquí está, disfruta. http://www.box.com/s/p7exfvxcvzgneo97d1of – Reuven

3

¡Gracias por tu solución! Me conseguiste el 90% del camino hasta allí. En pago, le daré el último 10% :)

El problema parece ser que es que la ventana UI nunca se gira, ¡solo sus subvistas lo hacen! Entonces la solución es usar una subvista.

También he agregado un código que muestra cómo ver qué celda se selecciona (suponiendo que su vista maestra es un UITableViewController).

- (IBAction)handleGesture:(UIGestureRecognizer *)gesture 
    { 
     CGPoint location; 
     UIWindow *window = [UIApplication sharedApplication].delegate.window; 

     //The window doesn't seem to rotate, so we'll get the subview, which does! 
     UIView *dragFeedback = [window.subviews objectAtIndex:0]; 
     if (gesture.state == UIGestureRecognizerStateBegan) { 
      location = [gesture locationInView:dragFeedback]; 

      //which cell are we performing the long hold over? 
      NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:[gesture locationInView:self.tableView]]; 
      UITableViewCell *selecteCell = [self.tableView cellForRowAtIndexPath:indexPath]; 
      NSLog(@"Cell %@", selecteCell); 

      // Create draggable view 
      _draggedView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"someImage.png"]]; 

      // Create drag-feedback window, add the drag-view and make the drag-window visible 
      [_draggedView setCenter:location]; 
      [dragFeedback addSubview:_draggedView]; 
     } 
     else if (gesture.state == UIGestureRecognizerStateChanged) { 
      // Update drag-view location 
      location = [gesture locationInView:dragFeedback]; 
      [_draggedView setCenter:location]; 
     } 
     else if (gesture.state == UIGestureRecognizerStateEnded) 
     { 
      // Disconnect drag-view and hide drag-feedback window 
      [_draggedView removeFromSuperview];  

      // Get final location in detailViewController coordinates 
      location = [gesture locationInView:self.detailViewController.view]; 
      [_draggedView setCenter:location]; 
      [self.detailViewController.view addSubview:_draggedView]; 
     } 
     else { 
      NSLog(@"%s unrecognized gesture %d", __FUNCTION__, gesture.state); 
     } 
    } 
+1

RefuX, aunque su cambio "limpia" la necesidad de la rotación manual, ya no brinda retroalimentación visual de arrastrar "en la parte superior" del menú ... Vea el ejemplo que publiqué: http://www.box.com/ s/p7exfvxcvzgneo97d1of – Reuven

+0

Ahhh .. Nunca probé en el modo vertical :) Sí, creo que para pasar por encima de la ventana emergente debería dibujar en la ventana UI. Investigué un poco más y confirmé que: "la ventana en sí misma no cambia los sistemas de coordenadas, aplica una transformación a sus subvistas que cambia su sistema de coordenadas". Entonces, ¿al menos todo tiene sentido ahora? :) – RefuX

+0

Claro. Gracias por confirmar. – Reuven

Cuestiones relacionadas