Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pinch to take photo full screen like Reeder apps

Trying to come up with a method for doing the exact same thing the reeder apps creator does in his iphone/ipad apps with pinch-to-expand photos to full screen.

I have a uiimageview in a table cell that I want to transition to a full screen view on pinch open, or maybe double tap. Would like to use a similar animation as well.

Any tips would be appreciated!

like image 691
Bob Spryn Avatar asked Dec 13 '22 10:12

Bob Spryn


1 Answers

Ok I managed to put this together myself. Not really sure how to use a transition method, but I needed to duplicate the view in the same location and then blow it up.

http://screencast.com/t/MLTuGkIYh

So in my cell that contains the big image I hook up both the pinch and tap gesture recognizers.

    self.imageView.contentMode = UIViewContentModeScaleAspectFit;
    self.imageView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
    UIPinchGestureRecognizer *pinchGesture = [[[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchGesture:)] autorelease];
    UITapGestureRecognizer *tapGesture = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)] autorelease];
    tapGesture.numberOfTapsRequired = 2;
    self.imageView.userInteractionEnabled = YES;
    self.imageView.multipleTouchEnabled = YES;
    [self.imageView addGestureRecognizer:pinchGesture]; 
    [self.imageView addGestureRecognizer:tapGesture];
    [cell.contentView addSubview:self.imageView];

and then here's the rest of the code. Basically when I recognized the gesture (and for pinching, make sure its finished) I place the duplicate view in the same exact location (gained via the convertRect stuff), and then animate its frame and background color. When returning from it, I do the inverse.

- (void)handlePinchGesture:(id)sender
{
    if (((UIPinchGestureRecognizer *)sender).state == UIGestureRecognizerStateEnded) {
        if(((UIPinchGestureRecognizer *)sender).view == self.imageView)
        {
            if (((UIPinchGestureRecognizer *)sender).scale > 1) {
                [self showFloorPlanFullScreen];
            }
        } else {
            if (((UIPinchGestureRecognizer *)sender).scale < 1) {
                [self closeFloorPlanFullScreen];
            }
        }
    }
}
- (void)handleTap:(id)sender
{
    if (((UITapGestureRecognizer *)sender).view == self.imageView) {
        [self showFloorPlanFullScreen];
    } else {
        [self closeFloorPlanFullScreen];
    }
}

- (void)showFloorPlanFullScreen
{
    CGRect newRect = [self.imageView convertRect:self.imageView.bounds toView:[self.splitViewController.view superview]];
    UIImage *image = self.imageView.image;
    self.fullScreenImageView = [[[UIImageView alloc] initWithImage:image] autorelease];

    UIPinchGestureRecognizer *pinchGesture = [[[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchGesture:)] autorelease];
    UITapGestureRecognizer *tapGesture = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)] autorelease];
    tapGesture.numberOfTapsRequired = 2;
    self.fullScreenImageView.userInteractionEnabled = YES;
    self.fullScreenImageView.multipleTouchEnabled = YES;
    [self.fullScreenImageView addGestureRecognizer:pinchGesture]; 
    [self.fullScreenImageView addGestureRecognizer:tapGesture];

    self.fullScreenImageView.contentMode = UIViewContentModeScaleAspectFit;
    self.fullScreenImageView.frame = newRect;
    self.fullScreenImageView.backgroundColor = [UIColor clearColor];
    [[self.splitViewController.view superview] addSubview:self.fullScreenImageView];

    CGRect splitViewRect = self.splitViewController.view.frame;
    [UIView animateWithDuration:0.5 animations:^{
        self.fullScreenImageView.backgroundColor = [UIColor blackColor];
        self.fullScreenImageView.frame = splitViewRect;
    }];
}


- (void)closeFloorPlanFullScreen
{
    CGRect newRect = [self.imageView convertRect:self.imageView.bounds toView:[self.splitViewController.view superview]];
    [UIView animateWithDuration:0.5 
                     animations:^{
        self.fullScreenImageView.backgroundColor = [UIColor clearColor];
        self.fullScreenImageView.frame = newRect;
                    } 
                     completion:^(BOOL finished) {
                         [self.fullScreenImageView removeFromSuperview];
                         self.fullScreenImageView = nil;
                     }];
}

If you want the picture to actual resize while zooming, I would recommend adding the duplicate view as soon as the pinching starts (and as long as its scaling > 1) and then apply the transformation:

CGAffineTransform myTransformation = CGAffineTransformMakeScale(((UIPinchGestureRecognizer *)sender).scale, ((UIPinchGestureRecognizer *)sender).scale);
self.fullScreenImageView.transform = myTransformation;

As soon as the pinching hits a end state, I would then fade in the black and adjust the frame. I decided not to go with this method as I think just recognizing the pinch out or double tap is good enough.

like image 166
Bob Spryn Avatar answered Feb 26 '23 10:02

Bob Spryn