Question

I have a UITableViewCell subclass and I have added a UIView to its contentView property. In order to enable dragging that subview, I have implemented the UIResponder appropriate methods:

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
  UITouch *touch = [touches anyObject];
  CGPoint currentLocation = [touch locationInView:self.superview];
  if (currentLocation.x >= self.rootFrame.origin.x) {
    return;
  }

  CGRect frame = self.frame;
  frame.origin.x = currentLocation.x;
  self.frame = frame;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
  self.frame = self.rootFrame; // rootFrame is a copy of the initial frame
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
 [self touchesEnded:touches withEvent:event];
}

The subview can be dragged without problem, but the cell is being selected as well, so that -tableView:didSelectRowAtIndexPath: is being called.

How can I prevent that the cell becomes selected when the subview is being dragged?

Was it helpful?

Solution 3

To solve this situation I wrote a protocol for the subview:

@protocol MyViewDelegate <NSObject>

///
/// Tells the delegate that touches has begun in view
///
- (void)view:(UIView *)view didBeginDragging:(UIEvent *)event;

///
/// Tells the delegate that touches has finished in view
///
- (void)view:(UIView *)view didFinishDragging:(UIEvent *)event;

@end

Then I completed the UIResponder methods in subview like this:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
  [self.delegate view:self didBeginDragging:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
  self.frame = self.rootFrame;
  [self.delegate view:self didFinishDragging:event];
}

Finally, I setup the cell as the delegate of the view and temporary cancel the cell selection while the dragging gestures are in progress:

- (void)view:(UIView *)view didBeginDragging:(UIEvent *)event {
  [self setHighlighted:NO animated:NO];
  [self setSelectionStyle:UITableViewCellSelectionStyleNone];
}

- (void)vView:(UIView *)view didFinishDragging:(UIEvent *)event {
  [self setSelectionStyle:UITableViewCellSelectionStyleGray];
}

That's it

OTHER TIPS

-[UITableViewCell setSelectionStyle: UITableViewCellSelectionStyleNone]

Of course, tableView:didSelectRowAtIndexPath: will still be called - so you might want to ignore the callback selectively.

It's impossible to tell exactly without knowing more informationg but there are several ways to achieve this:

  1. You can block the selection in UITableViewDelegate protocol by tableView:willSelectRowAtIndexPath:

  2. You can put your table into editing mode and use allowsSelectionDuringEditing

  3. You can block the selection/highlighting UI by overriding [UITableViewCell setSelected:animated:] or [UITableViewCell setHighligted:animated:]. The cell would still be selected though.

  4. You can disable the default table selection and use your own UITapGestureRecognizer (this is very easy by using [UITableView indexPathForRowAtPoint:]). With a custom recognizer, you can use its delegate to decide when your table receives a touch.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top