Как создать перетаскивание, аналогичное настройке панели инструментов Safari для iPad - PullRequest
2 голосов
/ 01 ноября 2011

У меня есть UIViewController, в котором есть как UITable, так и UIView.Я хочу иметь возможность выбирать элементы, отображаемые в UIView, и помещать их в ячейку в UITableView. Мне пришлось вернуться к использованию сенсорных событий в отличие от новых UIGestureRecognisers, чтобы сделать мгновенный снимок подключенного UIViewтак что этот моментальный снимок перетаскивается в UITableView, а не в UIView.Это прекрасно работает, используя следующее:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *t =[touches anyObject];

    UIGraphicsBeginImageContext(t.view.bounds.size);
    [t.view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    self.draggedView = [[UIImageView alloc] initWithImage:img];

    CGPoint centre = [[touches anyObject] locationInView:self.view];
    [self.draggedView setCenter:centre];
    [self.draggedView setAlpha:0.5];
    [self.view addSubview:self.draggedView];   
}

Однако в событии touchesEnded, когда я пытаюсь оценить, на каком UIView закончилось касание, я всегда получаю UIView вместо UITableView, когда я на него падаю.Любые идеи будут приветствоваться.

Ответы [ 2 ]

2 голосов
/ 07 ноября 2011

Я думаю, что нашел лучшее решение этой проблемы, используя новейшие GestureRecognisers.Я использую следующий распознаватель жестов LongPress внутри моего базового контроллера TableView.

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
    if([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]){
        [gestureRecognizer addTarget:self action:@selector(longGestureAction:)];
    }
    return YES;
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    return YES;
}

-(void)longGestureAction:(UILongPressGestureRecognizer *)gesture{
    UITableViewCell *cell= (UITableViewCell *)[gesture view];

    switch ([gesture state]) {
        case UIGestureRecognizerStateBegan:{          
            NSIndexPath *ip = [self.tableView indexPathForCell:cell];
            [self.tableView setScrollEnabled:NO];
            if(ip!=nil){
                [self.draggableDelegate dragAndDropTableViewController:self  draggingGestureWillBegin:gesture forCell:cell];
                UIView *draggedView = [self.draggableDelegate dragAndDropTableViewControllerView:self ];
                //switch the view the gesture is associated with this will allow the dragged view to continue on where the cell leaves off from
                [draggedView addGestureRecognizer:[[cell gestureRecognizers]objectAtIndex:0]]; 
                [self.draggableDelegate dragAndDropTableViewController:self draggingGestureDidBegin:gesture forCell:cell];
            }
        }
            break;
        case UIGestureRecognizerStateChanged:{
            [self.draggableDelegate dragAndDropTableViewController:self draggingGestureDidMove:gesture];
        }
            break;
        case UIGestureRecognizerStateEnded:{
            UIView *draggedView = [self.draggableDelegate dragAndDropTableViewControllerView:self];
            if(draggedView==nil)
                return;

            //this does not seem like the best way to do this yet you really don't want to fire one after the other I don't think
            [self.draggableDelegate dragAndDropTableViewController:self draggingGestureDidEnd:gesture];
            [self.dropableDelegate dragAndDropTableViewController:self droppedGesture:gesture];           

            [self.tableView setScrollEnabled:YES];
            [self.tableView reloadData];
        }
            break;

//        case UIGestureRecognizerStateCancelled:
//        case UIGestureRecognizerStateFailed:
//        case UIGestureRecognizerStatePossible:
//            [self.dragAndDropDelegate dragAndDropTableViewController:self draggingGesture:gesture endedForItem:nil];
            break;
        default:
            break;
    }
}

В TableViews, расширяющих этот базовый класс, я добавляю следующее в каждую ячейку в cellForIndexPath TableViewDataSource,

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:cell action:nil];
longPress.delegate = self;
[cell addGestureRecognizer:longPress];

и, наконец, все, что вам нужно сделать, это реализовать методы делегата следующим образом:

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
    if([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]){
        [gestureRecognizer addTarget:self action:@selector(longGestureAction:)];
    }
    return YES;
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    return YES;
}

-(void)longGestureAction:(UILongPressGestureRecognizer *)gesture{
    UITableViewCell *cell= (UITableViewCell *)[gesture view];

    switch ([gesture state]) {
        case UIGestureRecognizerStateBegan:{          
            NSIndexPath *ip = [self.tableView indexPathForCell:cell];
            [self.tableView setScrollEnabled:NO];
            if(ip!=nil){
                [self.draggableDelegate dragAndDropTableViewController:self  draggingGestureWillBegin:gesture forCell:cell];
                UIView *draggedView = [self.draggableDelegate dragAndDropTableViewControllerView:self ];
                //switch the view the gesture is associated with this will allow the dragged view to continue on where the cell leaves off from
                [draggedView addGestureRecognizer:[[cell gestureRecognizers]objectAtIndex:0]]; 
                [self.draggableDelegate dragAndDropTableViewController:self draggingGestureDidBegin:gesture forCell:cell];
            }
        }
            break;
        case UIGestureRecognizerStateChanged:{
            [self.draggableDelegate dragAndDropTableViewController:self draggingGestureDidMove:gesture];
        }
            break;
        case UIGestureRecognizerStateEnded:{
            UIView *draggedView = [self.draggableDelegate dragAndDropTableViewControllerView:self];
            if(draggedView==nil)
                return;

            //this does not seem like the best way to do this yet you really don't want to fire one after the other I don't think
            [self.draggableDelegate dragAndDropTableViewController:self draggingGestureDidEnd:gesture];
            [self.dropableDelegate dragAndDropTableViewController:self droppedGesture:gesture];           

            [self.tableView setScrollEnabled:YES];
            [self.tableView reloadData];
        }
            break;

//        case UIGestureRecognizerStateCancelled:
//        case UIGestureRecognizerStateFailed:
//        case UIGestureRecognizerStatePossible:
//            [self.dragAndDropDelegate dragAndDropTableViewController:self draggingGesture:gesture endedForItem:nil];
            break;
        default:
            break;
    }
}

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

1 голос
/ 02 ноября 2011

Итак, решение, которое я придумала, которое позволяет мне перетащить представление и поместить его в ячейку табличного представления, задав свойство изображения ячеек в соответствии с перетаскиваемым UIView, выглядит следующим образом.

Сначала мне пришлось реализовать touchMoved, чтобы переместить смешанное представление альфа, когда оно перетаскивается в ячейку, на которую оно перетаскивается.

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    CGPoint centre = [[touches anyObject] locationInView:self.view];
    [self.draggedView setCenter:centre];

}

Затем на touchesEnded я выполнил тест на просмотр таблицы, который возвращает UITableViewCellContentView (UIView * hit). Запрашивая суперпредставление просмотра попаданий, вы получаете попадание в ячейку, позволяющее установить его изображение.

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{

    CGPoint centre = [[touches anyObject] locationInView:self.view];
    UIView *hit = [self.tableView hitTest:centre withEvent:event];

    UIGraphicsBeginImageContext(self.draggedView.bounds.size);
    [self.draggedView.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    if(hit!=nil){
        UITableViewCell *tvc = (UITableViewCell *)hit.superview;
        [tvc.imageView setImage:img];
    }

    [self.draggedView removeFromSuperview];
    self.draggedView = nil;
}

Надеюсь, это кому-нибудь поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...