如何创建类似于Safari的safari工具栏自定义的拖放 [英] How to create a drag and drop similar to safari toolbar customisation for iPad

查看:152
本文介绍了如何创建类似于Safari的safari工具栏自定义的拖放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个UIViewController,它有一个UITable和一个UIView。我想要能够拿起显示在UIView中的项目,并将它们放在UITableView中的单元格上。我不得不恢复使用触摸事件而不是新的UIGestureRecognisers来拍摄UIView轻拍所以这个快照被拖动到UITableView而不是触摸的UIView。这样可以使用以下功能,

   - (void)touchesBegan:(NSSet *)与Event:(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 center = [[touches anyObject] locationInView:self.view];
[self.draggedView setCenter:center];
[self.draggedView setAlpha:0.5];
[self.view addSubview:self.draggedView];
}

然而,在我尝试评估哪个UIView触摸结束的touchesEnded事件中当我放弃它时,我总是得到一个UIView而不是UITableView。任何想法都是非常受欢迎的。

解决方案

我想我已经使用最新的GestureRecognisers更好地解决了这个问题。我使用以下的基本TableView控制器中的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 *)手势{
UITableViewCell * cell =(UITableViewCell *)[手势视图];

开关([手势状态]){
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];
//切换视图与此相关联的手势将允许拖动的视图继续从单元格离开
[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;

//这似乎不是最好的方式来做到这一点,但你真的不想一个接一个地发火,我不认为
[self.draggableDelegate dragAndDropTableViewController:self draggingGestureDidEnd:手势];
[self.dropableDelegate dragAndDropTableViewController:self droppedGesture:gesture];

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

// case UIGestureRecognizerStateCancelled:
// case UIGestureRecognizerStateFailed:
// case UIGestureRecognizerStatePossible:
// [self.dragAndDropDelegate dragAndDropTableViewController:self dragingGesture:gesture endsForItem:nil ]。
break;
默认值:
break;
}
}

在扩展这个基类的TableView中,我添加跟随到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 *)手势{
UITableViewCell * cell =(UITableViewCell *)[手势视图];

开关([手势状态]){
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];
//切换视图与此相关联的手势将允许拖动的视图继续从单元格离开
[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;

//这似乎不是最好的方式来做到这一点,但你真的不想一个接一个地发火,我不认为
[self.draggableDelegate dragAndDropTableViewController:self draggingGestureDidEnd:手势];
[self.dropableDelegate dragAndDropTableViewController:self droppedGesture:gesture];

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

// case UIGestureRecognizerStateCancelled:
// case UIGestureRecognizerStateFailed:
// case UIGestureRecognizerStatePossible:
// [self.dragAndDropDelegate dragAndDropTableViewController:self dragingGesture:gesture endsForItem:nil ]。
break;
默认值:
break;
}
}

你可以找到这个这里。花了我很长时间才能得到这个权利,所以我真的希望这可以节省别人的时间。


I have a UIViewController that has both a UITable and a UIView on it. I want to be able to pick up items that are displayed in the UIView and drop them on to a cell in the UITableView.I have had to revert to using touch events as opposed to the new UIGestureRecognisers to take a snap shot of the UIView tapped so that this snap shot is dragged over to the UITableView as opposed to the UIView touched. This works great using the following,

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

However, in the touchesEnded event when I try to evaluate which UIView the touch ended on I always get a UIView instead of the UITableView when I drop on it. Any ideas would be very welcome.

解决方案

I think I have come up with better solution to this problem using the latest GestureRecognisers. I use the following LongPress Gesture Recogniser inside my base TableView Controller.

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

In the TableViews that extend this base class I add the following to each cell in the cellForIndexPath TableViewDataSource,

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

and finally all you need to do is implement the delegate methods like so,

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

You can find the source for this here. It took me a long time to get this right so I really hope this saves someone else the time.

这篇关于如何创建类似于Safari的safari工具栏自定义的拖放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆