Limiting vertical movement of UIAttachmentBehavior inside a UICollectionView

If you're using iOS 9 and above then sliding function within attachment class will work perfectly for that job:

class func slidingAttachmentWithItem(_ item: UIDynamicItem,
                attachmentAnchor point: CGPoint,
               axisOfTranslation axis: CGVector) -> Self

it can be used easily, and it's very effective for sliding Apple documentation


One way to solve this is to use the inherited .action property of the attachment behavior.

You will need to set up a couple of variables first, something like (going from memory, untested code):

BOOL limitVerticalMovement = TRUE;
CGFloat staticCenterY = CGRectGetHeight(self.collectionView.frame) / 2;

Set these as properties of your custom UICollectionViewFlowLayout

When you create your attachment behavior:

UIAttachmentBehavior *attachment = [[UIAttachmentBehavior alloc] initWithItem:item attachedToAnchor:center];
attachment.damping = 1.0f;
attachment.frequency = 1.5f;
attachment.action = ^{
    if (!limitVerticalMovement) return;

    CGPoint center = item.center;
    center.y = staticCenterY;
    item.center = center;
};

Then you can turn the limiting function on and off by setting limitVerticalMovement as appropriate.