0

I have a custom UITableViewCell to implement swiping horizontally with UIAttachmentBehavior and a UIPanGestureRecognizer. Here's the relevant portion, in the UITableViewCell subclass:

- (void)panDidChange:(UIPanGestureRecognizer *)gesture {
CGPoint location = [gesture locationInView:[self tableView]];
location.y = CGRectGetMidY(self.frame);
switch (gesture.state) {
    case UIGestureRecognizerStateBegan: {
        self.panAttachment = [[UIAttachmentBehavior alloc] initWithItem:self attachedToAnchor:location];
        [self.animator addBehavior:self.panAttachment];

        break;
    }

Then, when UIGestureRecognizerStateChanged, I just set the self.panAttachment.anchorPoint as the location.

Now, this works fine from startup, but as soon as I add a cell to the tableView or delete a cell from the tableView and try to swipe, the cell moves to it's previous position before the tableView change (one cell down if a cell was deleted, one cell up if a cell was added). As far, as I can tell, this is because the cell's frame isn't being updated when it's position in the tableView changes, so location's y coordinate is out of sync. I've tried [self setNeedsDisplay] and all other "Update view" methods I could find, to no avail.

I am creating the animator referenced above like so:

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:[self tableView]];
larsacus
  • 7,346
  • 3
  • 26
  • 23
Januzellij
  • 177
  • 1
  • 1
  • 10

1 Answers1

0

It looks like the issue is in a couple different places:

  1. Your animator is being initialized with your entire table view as the reference view.
  2. You are then creating the attachment behavior with an anchor of midY in the tableView's coordinate system, meaning your attachment behavior is now anchored to a point in the tableView's reference coordinate system that is wherever the center point of the cell is located. I bet if you tried to scroll your tableView, weird things would also happen.

Depending on what your goal is for your dynamics behavior, you need to modify both your animator's reference frame and attachment's anchor point in order to fully define what physics simulation you are trying to achieve. Based on the above, it looks like you are trying to simply move the entire cell on the pan. I would recommend that you try moving only a specific container view inside your view hierarchy instead since the table view is going to be placing your cells directly using frames.

If you are looking to provide a pan with a snap-back effect on cancel, then this effect might be better implemented using a couple of UIAttachmentBehavior instances. One behavior instance to anchor the view you are wanting to swipe to it's resting position, and one to actually perform the panning and move the view like you are doing above during the pan. You can tweak the interaction between the two interactions by changing the damping and frequency. This question is a good reference for dragging in general using dynamic items.

In summary to fix your current issue:

  1. Define your animator's reference bounds to the cell's coordinate system, preferably using cell.contentView
  2. Have your cell manage the animator directly since the animator should only be concerned with a view in it's coordinate system. Your animator should have no knowledge of the table view's view hierarchy. Add/remove UIDynamicBehavior items from your cell's animator.
Community
  • 1
  • 1
larsacus
  • 7,346
  • 3
  • 26
  • 23
  • I'm a little confused. The location y coordinate is the mid y of the tableviewcell frame, not the tableview frame. This is in the cell subclass, so self is the cell. – Januzellij Mar 08 '14 at 03:09
  • I apologize, yes you are right. But `location` is still being calculated using tableView and the MidY you are using for y still returns a point in your tableView's coordinate system, not the cell's. – larsacus Mar 08 '14 at 15:45