关于如何将项目从UITableView拖放到UITableView的教程

时间:2010-08-14 03:10:13

标签: ios objective-c uitableview drag-and-drop touches

我一直在敲打这个,我想出来了。我想回馈社区,因为我从这个网站得到了很多帮助:)。

我正在尝试将项目从一个UITableView复制到另一个UITableView,我在网上看到的有关如何执行此操作的信息充其量只是粗略的。我自己想出来,所以我会描述我的小建筑。

  • 大师UIView
    • 使用UITableView进行UIView
      • 自定义UITableViewCell
        • 复制的自定义UIView(在我的情况下为Person对象)
    • 使用UITableView进行UIView
      • 自定义UITableViewCell
        • 复制的自定义UIView(在我的情况下为Person对象)

我在UITableView中拥有的person对象是我想要从一个表拖放到另一个表中的对象。我最困难的想法是如何将物品从桌子中弹出并以一个平滑的动作拖动它。在最长的时间内,我需要进行两次触摸才能执行操作。

从Person对象开始,这是一个包含图像的简单对象。我必须实现自己的touchesMoved方法,以便在发生拖动时更改Person的中心位置。

-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    if( m_moveable == YES ){
        UITouch *touch = [touches anyObject];
        CGPoint location = [touch locationInView:self.superview];

        if( 0 < location.x-50 && location.x+50 < 768 ){ 
            if( 0 < location.y-50 && location.y+150 < 1004 ){
                self.center = location;
            }
        }
    }
}

我在初始化时将Person对象的userInteractionEnabled标志设置为NO,这样表中的任何单击都不会被Person对象捕获。在这种情况下,Person对象将在表中移动,这违背了目的。

下一个对象是我的自定义UITableViewCell。该对象负责捕获用户的第一次触摸。它应该做的是抓住这个触摸并“弹出”这个人。 Person是属于自定义UITableViewCell的子视图之一。

 - (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UIView *parent = self.superview.superview.superview;    

    Person *s = nil;
    for( UIView *child in self.subviews ){
        if( [child isKindOfClass:[Person class]] ){
            s = child;
            s removeFromSuperview];
            break;
        }        
    }

    if( s != nil ){
        self.userInteractionEnabled = NO;
        s.userInteractionEnabled = YES;
        UITableView *subParent = self.superview;   //EDIT #1
        subParent.scrollEnabled = NO;              //EDIT #1

        [parent addSubview:s];
        //[self touchesEnded:touches withEvent:event]; //EDIT #1
    }
}

重要的是要注意在上面的方法中翻转userInteractionEnabled标志。在触摸之前,Person对象对于人的触摸是“禁区”。在自定义单元格捕获移动后,通过将Person添加到父视图然后激活(userInteractionEnabled = YES)来释放Person。 Person对象然后“诞生”并且可以自己处理移动触摸。

这有一个小故障,因为Person对象在左上角闪烁,但随后立即下降到用户的手指。

这个设计的最后一部分是UIView大师需要处理“触摸过渡”。当用户触摸表并且弹出Person对象时,应用程序需要意识到需要从表中移除焦点并将其指向Person对象。这样做的方式是主UIView中的hitTest方法被重载了以下内容。

- (UIView*) hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    UIView *rv = nil;
    for(UIView *child in self.subviews){
        if( [child isKindOfClass:[Person class]] ){
            rv = child;
            child.center = point;
            break;
        }
    }
    if( rv == nil ){
        rv = [super hitTest:point withEvent:event];
    }   
    return rv;
}

此代码的工作方式是,当Person从表中弹出时,它没有专注于它的触摸。触摸由UITableView“拥有”,从中弹出Person。 hitTest方法是重新聚焦触摸的关键。通常,系统会检查哪个UIView是触摸的焦点。系统调用hitTest方法来识别UIView。当Person附加到主视图时,此hitTest函数遍历所有子视图并检测Person的存在并将其作为“显性”触摸对象返回。手指的任何移动都会立即报告给Person而不是UITableView。

这是实施的胆量。要让UITableView“捕获”移动对象现在很简单,我会留给你试试!    如果您有任何疑问,请发布!

编辑#1    删除Person对象证明比我想象的更难:)。我必须添加一行来阻止UITableView在移动父项时滚动,因为UITableView正在吸收所有的移动事件。
   touchesEnded函数在自定义UITableViewCell类中触发         MJ

1 个答案:

答案 0 :(得分:7)

您好我已经设法在UITableView中创建一行拖放到同一个表的另一行。我创建了一个表示移动项目的uiImageView(未从表中删除)并将其附加到最前面的UIView,以使其在整个屏幕上可拖动。 这里有一些关于我面临的痛苦的帖子:

  1. UITableView: Drag a row onto another one
  2. UITableView: scrolling programmatically the content view
  3. UITableView: custom gestures make it scrolling no more
  4. 希望这可以帮助^^