Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

zoom entire UICollectionView

I have an iPad App where I'm using a UICollectionView and each UICollectionViewCell contains just a single UIImage. Currently I'm displaying per 9 UIImages (3 rows * 3 columns) per page, I have several pages.

I would like to use Pinch Gesture to zoom on the entire UICollectionView to increase/decrease the number of row/columns displayed per page and the best would be to have beautiful zoom animation during the Pinch gesture!

Currently, I have added a Pinch Gesture on my UICollectionView. I catch the Pinch Gesture event to compute the number of rows/columns using the scale factor, if it has changed then I update the full UICollectionView using:

[_theCollectionView performBatchUpdates:^{
     [_theCollectionView deleteSections:[NSIndexSet indexSetWithIndex:0]];
     [_theCollectionView insertSections:[NSIndexSet indexSetWithIndex:0]];
 } completion:nil];

It works but I don't have smooth animation during the transition.

Any idea? UICollectionView inherits from UIScrollView, is there a possibility to re-use the UIScrollView Pinch gesture feature to reach my goal?

like image 675
sebastien Avatar asked May 06 '13 19:05

sebastien


2 Answers

I'm assuming you're using the default UICollectionViewDelegateFlowLayout, right? Then make sure you respond accordingly to the delegate methods, and when the pinch gesture occurs, simply invalidate the layout.

For example, if I want to adjust the size of every item, while pinching:

@interface ViewController () <UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout>

@property (nonatomic,assign) CGFloat scale;
@property (nonatomic,weak)   IBOutlet UICollectionView *collectionView;

@end

@implementation ViewController
- (void)viewDidLoad
{
    [super viewDidLoad];

    self.scale = 1.0;

    [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"];

    UIPinchGestureRecognizer *gesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(didReceivePinchGesture:)];
    [self.collectionView addGestureRecognizer:gesture];

}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return CGSizeMake(50*self.scale, 50*self.scale);
}

- (void)didReceivePinchGesture:(UIPinchGestureRecognizer*)gesture
{
    static CGFloat scaleStart;

    if (gesture.state == UIGestureRecognizerStateBegan)
    {
        scaleStart = self.scale;
    }
    else if (gesture.state == UIGestureRecognizerStateChanged)
    {
        self.scale = scaleStart * gesture.scale;
        [self.collectionView.collectionViewLayout invalidateLayout];
    }
}

The property self.scale is just for show, you can apply this same concept to any other attribute, this doesn't require a beginUpdates/endUpdates because the user himself is carrying the timing of the scale.

Here's a running project, in case you want to see it in action.

like image 69
Can Avatar answered Sep 23 '22 07:09

Can


Sorry for my 2 cents question, I have found the solution, very simple.

In my PinchGesture callback I have just done the following:

void (^animateChangeWidth)() = ^() {
    _theFlowLayout.itemSize = cellSize;
};

[UIView transitionWithView:self.theCollectionView 
                  duration:0.1f 
                   options:UIViewAnimationOptionCurveLinear 
                animations:animateChangeWidth 
                completion:nil];

All cells of my UICollectionView are successfully changed and with a nice transition.

like image 39
sebastien Avatar answered Sep 25 '22 07:09

sebastien