Reputation: 677
I have an UIScrollView which populated with UIImageView. I'd like to have each UIImageView to be able to zoom & pan, and flick to the next page, just like iPhone's Photos app. I have searched around and what I have so far is this:
NSArray *pages = [self loadImages];
_pageScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
NSUInteger pageCount = [pages count]; // Adjustable
for (int i = 0; i < pageCount; i++) {
CGFloat x = i * self.view.frame.size.width;
// Page Settings
UIImageView *pageView = [[UIImageView alloc] initWithFrame:CGRectMake(x, 0, self.view.frame.size.width, self.view.frame.size.height)];
pageView.backgroundColor = [UIColor greenColor];
pageView.image = [pages objectAtIndex:i];
pageView.userInteractionEnabled = YES;
pageView.tag = i;
UIScrollView *pageScroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
pageScroll.maximumZoomScale = 2.0f;
pageScroll.minimumZoomScale = 1.0f;
pageScroll.zoomScale = 1.0f;
pageScroll.bouncesZoom = YES;
pageScroll.contentSize = CGSizeMake(pageView.frame.size.width, pageView.frame.size.height);
pageScroll.pagingEnabled = NO;
pageScroll.delegate = self;
[pageScroll addSubview:pageView];
// Gesture Reocgnisers
UIPinchGestureRecognizer *pinchGr = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchImage:)];
pinchGr.delegate = self;
[pageView addGestureRecognizer:pinchGr];
UIPanGestureRecognizer *panGr = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panImage:)];
[pageView addGestureRecognizer:panGr];
[_pageScrollView addSubview:pageView];
}
_pageScrollView.contentSize = CGSizeMake(self.view.frame.size.width * pageCount, self.view.frame.size.height);
_pageScrollView.pagingEnabled = YES;
_pageScrollView.delegate = self;
[self.view addSubview:_pageScrollView];
They just work fine for just paging (horizontal scrolling). However, I'm stack at how to implement UIGestures for each UIImageView. And with the help from various good questions & answers here in stackoverflow, I have implemented Zoom & Pan like this:
- (void) pinchImage:(UIPinchGestureRecognizer*)pgr {
[self adjustAnchorPointForGestureRecognizer:pgr];
if ([pgr state] == UIGestureRecognizerStateBegan || [pgr state] == UIGestureRecognizerStateChanged) {
CGFloat currentScale = pgr.view.frame.size.width / pgr.view.bounds.size.width;
CGFloat newScale = currentScale * pgr.scale;
if (newScale < 1.01f) {
newScale = 1.01f;
}
if (newScale > 3.0f) {
newScale = 3.0f;
}
CGAffineTransform transform = CGAffineTransformMakeScale(newScale, newScale);
pgr.view.transform = transform;
pgr.scale = 1;
}
}
- (void) panImage:(UIPanGestureRecognizer*)panGr {
if ([panGr state] == UIGestureRecognizerStateBegan || [panGr state] == UIGestureRecognizerStateChanged) {
CGPoint p = [panGr translationInView:self.view];
NSLog(@"[PAMPHLET PAGE]: Point: %@", NSStringFromCGPoint(p));
CGPoint movedPoint = CGPointMake(panGr.view.center.x + p.x, panGr.view.center.y + p.y);
if (panGr.view.frame.size.width > panGr.view.center.x + p.x &&
panGr.view.frame.size.height > panGr.view.center.y + p.y) {
panGr.view.center = movedPoint;
NSLog(@"Current: %f / %f", panGr.view.center.x, panGr.view.center.y);
}
[panGr setTranslation:CGPointZero inView:self.view];
}
}
This works almost there, but has several problems. Both Zoom & Pan is not limited to the scale of UIImageView, and when zoomed out or pan out to the outside of bounds, the image exceeds to the next view and everything gone wrong. I'm still figuring out this but don't know where should I start this.
How can I 'limit' those gesture's effective area, or should I try another method? Is this even the right approach to achieve this? I just wanted to make simple photo gallery like Photos app...
Please, any help would be appreciated.
Thank you.
Upvotes: 0
Views: 2063
Reputation: 3738
If you use MWPhotoBrowser from here, it will take care of downloading remote images too in addition to functionalities you are expecting.
Upvotes: 2