GestureRecognizer仅适用于一个单元格

时间:2015-03-15 19:21:16

标签: ios objective-c uitableview uigesturerecognizer

我试图用gestureRecognizer来刷我的细胞:

- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell Identifier";

    self.cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
    // Fetch Bookmark
    NSDictionary *bookmark = [self.bookmarks objectAtIndex:indexPath.row];

    // Configure Cell
    self.cell.textLabel.numberOfLines = 0;
    self.cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
    self.cell.textLabel.text = [bookmark objectForKey:@"name"];
    self.cell.detailTextLabel.text = [bookmark objectForKey:@"url"];

    //Swipe recognizer
    UIGestureRecognizer* recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
    [self.cell addGestureRecognizer:recognizer];

    return self.cell;
}

我有那些方法可以使我的细胞移动,但当我释放触摸手势时也会回到它们的初始位置:

-(BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer {
    CGPoint translation = [gestureRecognizer translationInView:self.cell];
    // Check for horizontal gesture
    if (fabsf(translation.x) > fabsf(translation.y)) {
        return YES;
    }
    return NO;
}

-(void)handlePan:(UIPanGestureRecognizer *)recognizer {
    // 1
    if (recognizer.state == UIGestureRecognizerStateBegan) {
        // if the gesture has just started, record the current centre location
        _originalCenter = self.cell.center;
    }

    // 2
    if (recognizer.state == UIGestureRecognizerStateChanged) {
        // translate the center
        CGPoint translation = [recognizer translationInView:self.cell];
        self.cell.center = CGPointMake(_originalCenter.x + translation.x, _originalCenter.y);
        // determine whether the item has been dragged far enough to initiate a delete / complete
        _deleteOnDragRelease = self.cell.frame.origin.x < -self.cell.frame.size.width / 2;

    }

    // 3
    if (recognizer.state == UIGestureRecognizerStateEnded) {
        // the frame this cell would have had before being dragged
        CGRect originalFrame = CGRectMake(0, self.cell.frame.origin.y,
                                          self.cell.bounds.size.width, self.cell.bounds.size.height);
        if (!_deleteOnDragRelease) {
            // if the item is not being deleted, snap back to the original location
            [UIView animateWithDuration:0.2
                             animations:^{
                                 self.cell.frame = originalFrame;
                             }
             ];
        }
    }
}

手势本身可以正常工作,但我只能滑动最后一个单元格,当我滚动UITableView时,它会成为我可以滑动的第一个单元格。

你有没有看到错误发生的地方?

2 个答案:

答案 0 :(得分:1)

我发现您的代码存在许多问题。

首先,您正在使用属性self.cell来创建手势识别器,以及您的handlePan:方法。

想一想。如果您尝试从表视图中的第3个单元格进行平移,为什么self.cell会神奇地包含正确的单元格?答案,它不会。

您需要转换代码,根据手势识别器中的信息确定要点击的单元格。手势识别器具有与其关联的视图,该视图是触发手势的视图。由于您将手势识别器直接附加到单元格,因此手势识别器的视图属性应该是用户正在拖动的单元格。 (您可能需要将手势识别器附加到cell.contentView而不是cell.view。这就是我一直以来所做的。但是如果将它直接附加到单元格上工作,那很好。这样可以更简单。)

下一个问题:每次调用cellForRowAtIndexPath时,您的代码都会向单元格添加手势识别器。如果一个单元格被回收,它已经附加了一个手势识别器,那么你将有2个手势识别器连接到单元格。然后,如果有一个长表视图并滚动更多,当它再次被回收时,它将有3.然后4,依此类推。坏。

如果手势识别器尚未添加手势识别器,则需要某种方法。一种方法是创建UITableViewCell的自定义子类,并将手势识别器直接附加到该单元的XIB文件中的单元格(或者在自定义单元格的init方法中)。这是我将使用的方法。

另一种方法是对代码进行较少的更改:将单元格出列后,请检查cell.gestureRecognizers.count。如果为零,请添加手势识别器。否则它已经有一个。 (注意:如果系统将一个或多个手势识别器附加到单元格,我不肯定。如果是这样,您可能需要修改逻辑以确定单元格是否已经附加了一个手势识别器。)

答案 1 :(得分:0)

        BOOL addGesture = true;
        for (int i = 0;i < cell.gestureRecognizers.count;i ++) {
            id gest = cell.gestureRecognizers[i];
            if ([gest isKindOfClass:[UIPanGestureRecognizer class]]) {
                addGesture = false;
                break;
            }

        }
        if (addGesture) {
            UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
            [cell.userImageView addGestureRecognizer: panRecognizer];
        }

这样我们就不依赖于苹果细胞结构的变化是安全的:)