Animating UICollectionViewCells

201 views Asked by At

I need to layout several collections of "buttons" in a circle. I have found UICollectionView using a custom layout flow to be an easy way to accomplish this. Especially since each collection of buttons varies in number.

In addition, this wheel of buttons needs to rotate (albeit slowly) like a ferris wheel. That is, each cell maintains it's orientation while the "wheel" rotates. So I have added a CAKeyFrameAnimation to each uicollectionviewcell.

The problem is now that I have lost the ability to select a cell while it is moving. Which is of course, because the cell is actually still at it's original location, only the presentation layer is animated.

I've seen suggestions for adding hittests to keyframe animated views, but doing this to a collectionviewcell seems to completely nullify the point of using a uicollectionview. And it feels like going down a rathole.

Am I missing something here? I feel like I should ditch UICollectionViews altogether for this application and use simple uiviews and hitTesting on the CALayer. Unfortunately though I have to re-invent many of the conveniences of collection views.

1

There are 1 answers

3
Hendrik Demmer On

If 'rotating' is an inherent property of your view, overriding hitTest to reflect this property seems totally valid to me.

I'd suggest wrapping both the UICollectionView and each of the cells into a UIView-derived RotatingView, rotating one clockwise, the other counter-clockwise at the same speed (you are probably already doing that).

Then override hitTest in RotatingView to something along these lines:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    CATransform3D transform = ((CALayer*)self.layer.presentationLayer).transform;
    CGFloat a = atan2(transform.m12, transform.m11);
    CGPoint offsetPoint = CGPointMake(point.x - CGRectGetWidth(self.frame)*0.5, point.y - CGRectGetHeight(self.frame)*0.5);
    CGPoint rotatedPoint = CGPointApplyAffineTransform(offsetPoint, CGAffineTransformMakeRotation(M_PI-a));
    CGPoint inverseOffsetRotatedPoint = CGPointMake(rotatedPoint.x + CGRectGetWidth(self.frame)*0.5, rotatedPoint.y + CGRectGetHeight(self.frame)*0.5);
    return [super hitTest:inverseOffsetRotatedPoint withEvent:event];
}