GestureRecognizer 仅适用于一个单元格
GestureRecognizer only works on one cell
我正在尝试使用 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
它成为我可以滑动的第一个单元格。
您是否看到错误可能来自何处?
我发现你的代码有很多问题。
首先是您正在使用 属性、self.cell 来创建您的手势识别器,并且也在您的 handlePan: 方法中。
想一想。如果您尝试从 table 视图中的第 3 个单元格开始平移,为什么 self.cell 会神奇地包含正确的单元格?回答,不会。
您需要转换代码以根据手势识别器的信息确定正在点击哪个单元格。手势识别器有一个与之关联的视图,即触发手势的视图。由于您将手势识别器直接附加到单元格,因此手势识别器的视图 属性 应该是用户正在拖动的单元格。 (您可能需要将手势识别器附加到 cell.contentView 而不是 cell.view。这就是我一直在做的。但是如果将它直接附加到单元格就可以了,很好。这使它更简单。)
下一个问题:每次调用 cellForRowAtIndexPath 时,您的代码都会向单元格添加手势识别器。如果一个单元格被回收,它已经附加了一个手势识别器,所以你将有 2 个手势识别器附加到单元格。然后,如果有一个长 table 视图并滚动更多,当它再次被回收时,它将有 3 个。然后是 4 个,依此类推。不好。
您需要一些方法来仅将手势识别器添加到单元格(如果它还没有手势识别器)。一种方法是创建 UITableViewCell 的自定义子类,并在该单元格的 XIB 文件中(或在自定义单元格的 init 方法中)直接将手势识别器附加到该单元格。这是我会使用的方法。
另一种对代码更改较少的方法:将单元格出队后,检查 cell.gestureRecognizers.count。如果它为零,请添加您的手势识别器。否则它已经有一个了。 (注意。我不确定系统是否将一个或多个手势识别器附加到单元格。如果是这样,您可能需要修改逻辑以确定单元格是否已经附加了一个手势识别器。)
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];
}
这样我们就不会依赖苹果细胞结构的变化来确保安全:)
我正在尝试使用 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
它成为我可以滑动的第一个单元格。
您是否看到错误可能来自何处?
我发现你的代码有很多问题。
首先是您正在使用 属性、self.cell 来创建您的手势识别器,并且也在您的 handlePan: 方法中。
想一想。如果您尝试从 table 视图中的第 3 个单元格开始平移,为什么 self.cell 会神奇地包含正确的单元格?回答,不会。
您需要转换代码以根据手势识别器的信息确定正在点击哪个单元格。手势识别器有一个与之关联的视图,即触发手势的视图。由于您将手势识别器直接附加到单元格,因此手势识别器的视图 属性 应该是用户正在拖动的单元格。 (您可能需要将手势识别器附加到 cell.contentView 而不是 cell.view。这就是我一直在做的。但是如果将它直接附加到单元格就可以了,很好。这使它更简单。)
下一个问题:每次调用 cellForRowAtIndexPath 时,您的代码都会向单元格添加手势识别器。如果一个单元格被回收,它已经附加了一个手势识别器,所以你将有 2 个手势识别器附加到单元格。然后,如果有一个长 table 视图并滚动更多,当它再次被回收时,它将有 3 个。然后是 4 个,依此类推。不好。
您需要一些方法来仅将手势识别器添加到单元格(如果它还没有手势识别器)。一种方法是创建 UITableViewCell 的自定义子类,并在该单元格的 XIB 文件中(或在自定义单元格的 init 方法中)直接将手势识别器附加到该单元格。这是我会使用的方法。
另一种对代码更改较少的方法:将单元格出队后,检查 cell.gestureRecognizers.count。如果它为零,请添加您的手势识别器。否则它已经有一个了。 (注意。我不确定系统是否将一个或多个手势识别器附加到单元格。如果是这样,您可能需要修改逻辑以确定单元格是否已经附加了一个手势识别器。)
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];
}
这样我们就不会依赖苹果细胞结构的变化来确保安全:)