I'm working on making a large grid using a UICollectionView
, and I want it to be zoomable (the entire UICollectionView
, not just a single cell) with the standard pinch-to-zoom gesture. The grid in question has a custom UICollectionViewLayout
, because I needed it to scroll both horizontally and vertically.
I got the layout working perfectly with this SO answer, so I had a grid that you could move all around on. The short version is that each row of cells is a section
of the view, and all the cells are positioned based on a uniform cellSize
of (to start with) 50.
Then I worked out the pinch-to-zoom ability using a modified version of this SO answer, where I basically change the layout's cellSize
value when the pinch gesture is received, and then invalidate the layout so it re-draws with the slightly larger or smaller layout. Thus, all the cells get bigger or smaller, and we have zooming.
Here's the code for the pinch gesture method:
-(void)didReceivePinchGesture:(UIPinchGestureRecognizer*)gesture {
double newCellSize = [(IMMapViewLayout *)_mainCollectionView.collectionViewLayout cellSize] * gesture.scale;
newCellSize = MIN(newCellSize, 100);
newCellSize = MAX(newCellSize, 15);
[(IMMapViewLayout *)_mainCollectionView.collectionViewLayout setCellSize:newCellSize];
[_mainCollectionView.collectionViewLayout invalidateLayout];
}
And everything was working (almost) perfectly.
My problem is this: it zooms from the top-left corner, not from where the pinch is located. Makes sense, I suppose, since we're redrawing everything and it's all a little bigger, but it's obviously not the desired effect.
My first thought was simply to detect the cell directly under the pinch and then use scrollToItemAtIndexPath:atScrollPosition:animated:
to move back to that cell instantaneously, but it doesn't seem to be working, and the animation gets super-choppy anyway. Also, if you're pinching anywhere other than the center of the screen, it would be hard to move it right back to that exact spot repeatedly during the zoom.
Here's what I've got now:
-(void)didReceivePinchGesture:(UIPinchGestureRecognizer*)gesture {
double newCellSize = [(IMMapViewLayout *)_mainCollectionView.collectionViewLayout cellSize] * gesture.scale;
newCellSize = MIN(newCellSize, 100);
newCellSize = MAX(newCellSize, 15);
[(IMMapViewLayout *)_mainCollectionView.collectionViewLayout setCellSize:newCellSize];
[_mainCollectionView.collectionViewLayout invalidateLayout];
if([gesture numberOfTouches] >= 2) {
CGPoint touch1 = [gesture locationOfTouch:0 inView:_mainCollectionView];
CGPoint touch2 = [gesture locationOfTouch:1 inView:_mainCollectionView];
CGPoint mid;
mid.x = ((touch2.x - touch1.x) / 2) + touch1.x;
mid.y = ((touch2.y - touch1.y) / 2) + touch1.y;
NSIndexPath *currentIndexPath = [_mainCollectionView indexPathForItemAtPoint:mid];
[_mainCollectionView scrollToItemAtIndexPath:currentIndexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:NO];
}
}
Can anyone help me make this UICollectionView
zoom, in its entirety, but centered on the position of the pinch?