2012-01-04 2 views
5

Я работаю над D & D в UISplitViewController (на основе проекта шаблона Xcode), от MasterViewController до DetailViewController.iOS (iPad) Drag & Drop в UISplitViewController

В основном, я делаю создание UILongPressGestureRecognizer и размещение его в свойстве self.tableview объекта MasterViewController.

Ниже представлен мой распознающий жест.

- (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); 
    } 
} 

Все работает очень хорошо, когда iPad находится в портретном режиме - перетаскивание, падение - работы.

Моя проблема начинается, если iPad повернут ... В этом случае мой _draggedView появляется «с вращением против часовой стрелки» - он будет «отражать» вращение iPad - до отказа.

Это, как я должен применить некоторое вращение _dragFeedbackWindow - но я попробовал несколько вещей, невнимание ...

Любая идея?

Спасибо!

ответ

4

OK - я понял, «почему» это происходит, и «КАК», чтобы исправить (и присоединит код обработчика, чтобы сделать это правильно, все ниже

Вот код ... «Просто. "добавить его в свой MAsterViewController (если - как я - вы хотите, чтобы перетащить от мастера к деталям ...)

// 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); 
} 

Теперь обработчик LongPress жест ...

- (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); 
    } 
} 

Этот работает как шарм - дайте мне знать, как это работает для вас (если вам нужен образец проекта, дайте мне знать ...)

+0

Hi Reuven, у меня такие же требования. Не могли бы вы, пожалуйста, поделиться образцом проекта, пожалуйста. Благодарю. – applefreak

+0

уверен. мне потребуется день на уборку. – Reuven

+1

Вот он, наслаждайтесь. http://www.box.com/s/p7exfvxcvzgneo97d1of – Reuven

3

Спасибо за ваше решение! Вы получили мне 90% пути. В оплате я дам вам последние 10% :)

Вопрос кажется тем, что UIWindow никогда не вращается, только его подвид! Таким образом, решение заключается в использовании подвью.

Я также добавил код, который показывает, как определить, какая ячейка выбрана (при условии, что ваш основной вид является 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, в то время как ваше изменение «очищает» необходимость ручного вращения, оно больше не обеспечивает визуальную обратную связь при перетаскивании «сверху» меню ... См. Пример, который я опубликовал: http://www.box.com/ s/p7exfvxcvzgneo97d1of – Reuven

+0

Ahhh .. Я никогда не тестировался в портретном режиме :) Да, я думаю, чтобы попасть выше окна всплывающего окна, которое вам нужно было бы нарисовать на UIWindow. Я сделал еще несколько исследований и подтвердил, что: «само окно фактически не меняет системы координат, оно применяет преобразование к его подзонам, которое меняет их систему координат». Так, по крайней мере, все это имеет смысл сейчас? :) – RefuX

+0

Несет. Спасибо, что подтвердили. – Reuven