0

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.

Electro-Bunny
  • 1,380
  • 2
  • 12
  • 33

1 Answers1

0

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];
}
Hendrik Demmer
  • 191
  • 1
  • 6
  • I am actually only trying animating the UICollectionViewCells themselves. The cells travel on CGPath Arcs inside the collection view. I *think* you are proposing though, rotating the entire collection view and rotating the cells to "correct" their orientation? If that would work, then the cells themselves would not really move with respect to the collection view and possibly would still be touchable? If that is the case, there would be no need to mess with hittest... I need to digest this a bit. thanks. – Electro-Bunny Dec 20 '13 at 19:00
  • `hitTest` will always use the `modelLayer`'s transform. If you want the touches to correctly translate to animated views (moved or rotated), you will have to transform the touch location accordingly. – Hendrik Demmer Dec 20 '13 at 19:04
  • Gotcha, very clever. I will give this a try. – Electro-Bunny Dec 20 '13 at 19:41