UITableView:自定义手势使其不再滚动

Posted

技术标签:

【中文标题】UITableView:自定义手势使其不再滚动【英文标题】:UITableView: custom gestures make it scrolling no more 【发布时间】:2011-03-25 23:20:29 【问题描述】:

我有一个 UIViewController,它包含一个 UITableView(子类)和另一个 UIView(子类)。它们位于同一层次结构级别,但 UIView 最后添加,因此它位于最前面。 我覆盖 touchesBegan/Moved/Ended 以拦截来自顶部 UIView 的手势:我的目标是获取选定的 UITableViewCell,如果双击,则创建一个要拖动的 ImageView。 我似乎完成了它,但现在我无法再滚动 UITableView,即使我转发了触摸事件。 下面是 UIView 的方法:

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    NSLog(@"BO");
    UITouch * touch = [touches anyObject];

    CGPoint tPoint = [touch locationInView:self];
    InventoryViewController * invViewCont = self.viewController;
    UITableView * invTab = invViewCont.inventoryTableView;
    [invTab deselectRowAtIndexPath:[invTab indexPathForSelectedRow] 
                          animated:YES];
    NSArray * cells = [invTab visibleCells];
    BOOL found = NO;
    for (UITableViewCell * cell in cells)
    
        if (CGRectContainsPoint(cell.frame, tPoint)) 
        
            [cell touchesBegan:touches withEvent:event];
            found = YES;
            break;
        
    


    if (!found)
    
        [invViewCont.inventoryTableView touchesBegan:touches withEvent:event];
    

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
        NSLog(@"Mo");
        UITouch * touch = [touches anyObject];
        CGPoint tPoint = [touch locationInView:self];

        copyObj.center = tPoint;
        InventoryViewController * invViewCont = self.viewController;
        UITableView * invTab = invViewCont.inventoryTableView;

        [invTab deselectRowAtIndexPath:[invTab indexPathForSelectedRow] 
                              animated:YES];
        NSArray * cells = [invTab visibleCells];
        BOOL found = NO;
        for (UITableViewCell * cell in cells)
        
            if (CGRectContainsPoint(cell.frame, tPoint)) 
            
                [cell touchesMoved:touches withEvent:event];
                found = YES;
                break;
            
        

        if (!found)
        
            [invViewCont.inventoryTableView touchesMoved:touches withEvent:event];
        

    

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

        UITouch * touch = [touches anyObject];
        if ([touch tapCount] == 2) 
        
            [self desubCopyView];
        
        CGPoint tPoint = [touch locationInView:self];
        copyObj.center = tPoint;
        InventoryViewController * invViewCont = self.viewController;
        UITableView * invTab = invViewCont.inventoryTableView;
        [invTab deselectRowAtIndexPath:[invTab indexPathForSelectedRow] 
                              animated:YES];
        NSArray * cells = [invTab visibleCells];
        BOOL found = NO;
        for (UITableViewCell * cell in cells)
        
            if (CGRectContainsPoint(cell.frame, tPoint)) 
            
                [cell touchesEnded:touches withEvent:event];
                //[cell.imageView touchesEnded:touches withEvent:event];
                found = YES;
                break;
            
        
        if (!found)
        
            [invViewCont.inventoryTableView touchesEnded:touches withEvent:event];
        
    

这是 UITableViewCell 中的那些

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    UITouch * touch = [touches anyObject];
    if ([touch tapCount] == 2) 
    
        CGPoint tPoint = [touch locationInView:self]; 
        NSLog(@"CellX %lf CY %lf", tPoint.x, tPoint.y);

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

        UIGraphicsEndImageContext();

        UIImageView * newView = [[UIImageView alloc] initWithImage:viewImage];
        [dragArea addSubview:newView];
        dragArea.copyObj = newView;
        [newView release];

        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:0.4];
        dragArea.copyObj.transform = CGAffineTransformMakeScale(1.3, 1.3);
        [UIView commitAnimations];
        tPoint = [self convertPoint:tPoint toView:dragArea];
        dragArea.copyObj.center = tPoint;
    
    [super touchesBegan:touches withEvent:event];


- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
    NSLog(@"MOV %@", self.imageView.image);
    [super touchesMoved:touches withEvent:event];


- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
    NSLog(@"ENDED");
    [super touchesEnded:touches withEvent:event];

在我的 UITableView 中,我只是:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    NSLog(@"BEGTB");
    [super touchesBegan:touches withEvent:event];


- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
    NSLog(@"MOVTB");
    [super touchesMoved:touches withEvent:event];


- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
        NSLog(@"ENDTB");
    [super touchesEnded:touches withEvent:event];

我肯定错过了什么,但我不知道是什么

【问题讨论】:

【参考方案1】:

我强烈建议您研究 UITapGestureRecognizer 而不是自己处理 touchesX 事件。

【讨论】:

双击后,我需要在用户拖动我创建的新视图时识别用户,只有那个 UIGestureRecognizer 可以吗? 我相信,如果您添加了 UIPanGestureRecognizer,您将能够检测到他们在拖动它。 在第二次阅读时,我不确定你想要的识别器是否可以实现 - 是你想要成为用户点击一次然后在第二次点击时用户离开手指并且图像视图是创建并拖动,还是用户双击然后创建图像视图,并且用户第三次放下手指是拖动图像视图的时间? 如果是前者,可能在单击一次(使用 UITapGestureRecognizer)时添加一个 UIPanGestureRecognizer,以防用户再次点击并尝试移动图像视图(您在平移手势识别器启动时创建识别)和一个计时器,用于在一定时间后停用平移手势识别器(对于用户只想要单击的情况)。 @BarrettJ 我希望像往常一样单击选择表格视图中的行,第二次点击创建图像视图,然后用户可以在不离开屏幕的情况下拖动它。我已经能够使用上面的代码做到这一点。问题是:我不再能够滚动底层的 tableview,因为最前面的 uiview 拦截了它,而且我似乎无法正确转发它。最终的目标其实是:用拖拽的imageview在table view上滚动,然后放到另一行(想象一下像编辑模式,但是导致放到一行)【参考方案2】:

我找到了一个解决方法,在我的自定义 UITableView 中覆盖触摸手势的方法,以便在我拖动对象时使其以程序方式滚动。 Here 是“解决方案”。

我仍然相信还有另一种更简单的方法可以做到这一点,但我没有找到它,所以发布这个并将其标记为“答案”可能会对其他人有所帮助。

【讨论】:

以上是关于UITableView:自定义手势使其不再滚动的主要内容,如果未能解决你的问题,请参考以下文章

更喜欢 UITableView 的重新排序控制手势而不是自定义平移手势

UITableView,如何修复页脚,使其在滚动时永远不会向上或向下移动?

如何让 UI 组件与我的 UITableView 一起滚动

是否可以在按钮上启动滚动视图平移手势

UITableViewCell 滚动检测

自定义 UITableview 单元格可访问性无法正常工作