Implement UIPageControl vertical scrolling - ios

I am trying to create a UIPageControl with vertical scrolling . By default you can slide only in horizontal direction ,but how can I slide it up to down ?
here is my code :
#pragma mark page control setup
- (void)setupPageScroll {
_pageControl.transform = CGAffineTransformMakeRotation(M_PI /2 );
_pageControl.currentPage = 0;
_pageControl.numberOfPages = 3;
[_scrollView setContentSize:CGSizeMake(_scrollView.frame.size.width * _pageControl.numberOfPages, _scrollView.frame.size.height)];
_scrollView.delegate = self;
[self createPageWithView:_tower1 forPage:0];
[self createPageWithView:_tower2 forPage:1];
[self createPageWithView:_tower3 forPage:2];
}
- (void)createPageWithView:(UIView *)iview forPage:(int)page
{
UIView *newView = [[UIView alloc] initWithFrame:
CGRectMake(_scrollView.frame.size.width * page, 0, _scrollView.frame.size.width, _scrollView.frame.size.height)];
[newView addSubview:iview];
[_scrollView addSubview:newView];
}
- (IBAction)pageChanged:(id)sender {
CGRect pageRect = CGRectMake(_pageControl.currentPage * _scrollView.frame.size.width, 0, _scrollView.frame.size.width, _scrollView.frame.size.height);
[_scrollView scrollRectToVisible: pageRect animated: YES];
}
- (void)scrollViewDidScroll: (UIScrollView *) sView
{
CGFloat offset = _scrollView.contentOffset.x;
CGFloat pageSize = _scrollView.frame.size.width;
int page = floor((offset + (pageSize/2)) / pageSize);
_pageControl.currentPage = page;
}

If You are using interface builder, just set this value as a User Defined Runtime Atrribute.
It works.
http://i.imgur.com/USBf2a9.png

Related

Zoom image and then scroll image to view next image, previous image not zooming out

I want to zoom out image to original size after scroll slider.
I'm using REPagedScrollView library to implement slider.
I have 5 images in slider. Now zoom-in 1st image and then immediately scroll slider to view 2nd image. Then go back to view 1st image. 1st image not zooming out. That image was still in zoom - in mode.
How can i solved this.
Thanks in advance.
I'm using this below code.
-(void)slideShow
{
[scrollView removeFromSuperview];
scrollView = [[REPagedScrollView alloc] initWithFrame:self.scrollVw.bounds];
scrollView.delegate=self;
scrollView.pageControl.pageIndicatorTintColor=[UIColor clearColor];
scrollView.pageControl.currentPageIndicatorTintColor=[UIColor clearColor];
current_page=0;
for(int i=0;i<[self.PhotoImgArr count];i++){
// Image view
image_scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0,0,self.scrollVw.frame.size.width,self.scrollVw.frame.size.height)];
self.image_view = [[AsyncImageView alloc] initWithFrame:CGRectMake(0,0, image_scroll.frame.size.width, image_scroll.frame.size.height)];
self.image_view.backgroundColor=[UIColor clearColor];
// self.image_view.contentMode = UIViewContentModeScaleAspectFit;
self.image_view.clipsToBounds = true;
self.image_view.userInteractionEnabled = YES;
//self.image_view.image=[UIImage imageNamed:#"Stars"];
self.image_view.imageURL =[NSURL URLWithString:[self.PhotoImgArr objectAtIndex:i]];
doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleTap:)];
[doubleTap setNumberOfTapsRequired:2];
[self.image_view addGestureRecognizer:doubleTap];
// twoFingerPinch = [[UIPinchGestureRecognizer alloc]
// initWithTarget:self
// action:#selector(twoFingerPinch:)];
// [self.image_view addGestureRecognizer:twoFingerPinch];
[image_scroll setDelegate:self];
[image_scroll setShowsHorizontalScrollIndicator:NO];
[image_scroll setShowsVerticalScrollIndicator:NO];
image_scroll.tag=i+1;
// image_scroll.backgroundColor=[UIColor purpleColor];
image_scroll.autoresizingMask=UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
self.image_view.autoresizingMask=UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
image_scroll.contentSize = CGSizeMake(self.image_view.bounds.size.width-500, self.image_view.bounds.size.height-300);
image_scroll.decelerationRate = UIScrollViewDecelerationRateFast;
[image_scroll setMaximumZoomScale:4.0];
// image_scroll.minimumZoomScale = 1.0;
[image_scroll setZoomScale:[image_scroll minimumZoomScale]];
//image_scroll.zoomScale = 1.0;
[image_scroll addSubview:self.image_view];
[scrollView addPage:image_scroll];
}
scrollView.autoresizingMask=UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
scrollView.tag=0;
[self.scrollVw addSubview:scrollView];
[scrollView scrollToPageWithIndex:self.selected_index animated:YES];
}
- (void)twoFingerPinch:(UIPinchGestureRecognizer *)recognizer
{
NSLog(#"twoFingerPinch");
float newScale = [image_scroll zoomScale] / 2.0;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[recognizer locationInView:recognizer.view]];
[image_scroll zoomToRect:zoomRect animated:YES];
}
- (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer {
// zoom in
NSLog(#"handleDoubleTap");
UIScrollView *imageScroll = (UIScrollView *)[self.view viewWithTag:self.selected_index+1];
float newScale = [imageScroll zoomScale] * 2.0;
if (newScale > imageScroll.maximumZoomScale){
newScale = imageScroll.minimumZoomScale;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];
[imageScroll zoomToRect:zoomRect animated:YES];
}
else{
newScale = imageScroll.maximumZoomScale;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];
[imageScroll zoomToRect:zoomRect animated:YES];
}
}
#pragma mark Utility methods
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center {
CGRect zoomRect;
// the zoom rect is in the content view's coordinates.
// At a zoom scale of 1.0, it would be the size of the imageScrollView's bounds.
// As the zoom scale decreases, so more content is visible, the size of the rect grows.
zoomRect.size.height = [image_scroll frame].size.height / scale;
zoomRect.size.width = [image_scroll frame].size.width / scale;
// choose an origin so as to get the right center.
zoomRect.origin.x = center.x - (zoomRect.size.width / 2.0);
zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0);
return zoomRect;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView1
{
UIScrollView *imageScroll = (UIScrollView *)[self.view viewWithTag:self.selected_index+1];
if(scrollView1.tag ==0){
CGFloat pageWidth = scrollView1.frame.size.width;
current_page = floor((scrollView1.contentOffset.x - pageWidth / 2.0) / pageWidth) + 1;
self.selected_index=current_page;
self.lblHeader.text=[NSString stringWithFormat:#"%ld of %lu",self.selected_index+1,(unsigned long)[self.PhotoImgArr count]];
}
else
{
CGFloat offsetX = (imageScroll.bounds.size.width > imageScroll.contentSize.width)?
(imageScroll.bounds.size.width - imageScroll.contentSize.width) * 0.5 : 0.0;
CGFloat offsetY = (imageScroll.bounds.size.height > imageScroll.contentSize.height)?
(imageScroll.bounds.size.height - imageScroll.contentSize.height) * 0.5 : 0.0;
[scrollView1.subviews objectAtIndex:0].center = CGPointMake(imageScroll.contentSize.width * 0.5 + offsetX,imageScroll.contentSize.height * 0.5 + offsetY);
}
}
-(UIView *) viewForZoomingInScrollView:(UIScrollView *)scrollView1
{
if([scrollView1.subviews count]>0){
return [scrollView1.subviews objectAtIndex:0];
}
return nil;
}
ok first of all, don't use REPagedScrollView instead u can set the pages to scrollview by changing the view's x position, and it is useful for your zooming, if u use REPagedScrollView there are some complications that u can't get the subview's as scrollview, instead u get a UIView instance
Better u use normal UIScrollView it is good for your case, and also set the UIPageControl as they are doing in REPagedScrollView as separately in view controller's view.
first set the pages like below
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_scrollPager = [[UIScrollView alloc] initWithFrame:self.view.bounds];
_scrollPager.delegate=self;
_scrollPager.pagingEnabled = YES;
_current_page=0;
_prev_next_index = 0;
_PhotoImgArr = [[NSMutableArray alloc] initWithObjects:#"00.jpg",#"01.jpg",#"02.jpg",#"03.jpg", nil];
CGSize totalContentSize = CGSizeMake(self.view.bounds.size.width [_PhotoImgArr count], self.view.bounds.size.height);
_scrollPager.contentSize = totalContentSize;
[self.view addSubview:_scrollPager];
[self setUpPager];
}
- (void)setUpPager
{
for(int i=0;i<[self.PhotoImgArr count];i++)
{
// Image view
UIScrollView *image_scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(i * self.view.bounds.size.width, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
UIImageView *image_view = [[UIImageView alloc] initWithFrame:image_scroll.bounds];
image_view.backgroundColor=[UIColor clearColor];
image_view.clipsToBounds = true;
image_view.image = [UIImage imageNamed:_PhotoImgArr[i]];
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleTap:)];
[doubleTap setNumberOfTapsRequired:2];
[image_scroll setDelegate:self];
[image_scroll setShowsHorizontalScrollIndicator:NO];
[image_scroll setShowsVerticalScrollIndicator:NO];
image_scroll.tag=i;
image_scroll.autoresizingMask=UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
image_view.autoresizingMask=UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
image_scroll.contentSize = image_scroll.bounds.size;
image_scroll.decelerationRate = UIScrollViewDecelerationRateFast;
image_scroll.minimumZoomScale = 1.0f;
image_scroll.maximumZoomScale = 3.0f;
[image_scroll addSubview:image_view];
[image_scroll addGestureRecognizer:doubleTap];
[_scrollPager addSubview:image_scroll];
}
_scrollPager.autoresizingMask=UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
_scrollPager.tag=100;
}
Handle the double tap action like below in same view controller
- (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer
{
// zoom in
NSLog(#"handleDoubleTap");
if(gestureRecognizer.view == _scrollPager) return;
UIScrollView *doubleTapScroll = [self getImageScroller];
if(doubleTapScroll)
{
//zoom
CGPoint pointInView = [gestureRecognizer locationInView:self.view];
CGFloat newZoomScale = doubleTapScroll.zoomScale * 1.5f;
newZoomScale = MIN(newZoomScale, doubleTapScroll.maximumZoomScale);
CGRect rectToZoomTo = CGRectZero;
CGFloat currentZoomScale = doubleTapScroll.zoomScale;
if(currentZoomScale == 1.0f)
{
rectToZoomTo = [self zoomRectForScrollView:doubleTapScroll withScale:newZoomScale withCenter:pointInView];//CGRectMake(x, y, w, h);
}
else if (currentZoomScale >= 1.0f)
{
rectToZoomTo = [self zoomRectForScrollView:doubleTapScroll withScale:1 withCenter:self.view.center];
}
[doubleTapScroll zoomToRect:rectToZoomTo animated:YES];
}
}
and one thing for scrollview u don't need to handle pinch, it will automatillcay handled for zooming.
finally handling of the zoom
#pragma mark Utility methods
- (CGRect)zoomRectForScrollView:(UIScrollView *)scrollView withScale:(float)scale withCenter:(CGPoint)center
{
CGRect zoomRect;
zoomRect.size.height = scrollView.frame.size.height / scale;
zoomRect.size.width = scrollView.frame.size.width / scale;
zoomRect.origin.x = center.x - (zoomRect.size.width / 2.0);
zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0);
return zoomRect;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView1
{
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
if(scrollView == _scrollPager)
{
float currentPage = scrollView.contentOffset.x /scrollView.frame.size.width;
if(currentPage != _current_page)
{
_prev_next_index = _current_page;
_current_page = ceil(currentPage);
[self resetScrollerAtViewIndex:_prev_next_index];
}
}
}
-(UIView *) viewForZoomingInScrollView:(UIScrollView *)scrollView1
{
if(scrollView1 == _scrollPager)
return nil;
else
{
UIScrollView *image_scroll = [self getImageScroller];
if(image_scroll)
if([image_scroll.subviews count]>0)
{
return [image_scroll.subviews objectAtIndex:0];
}
}
return nil;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (UIScrollView *)getImageScroller
{
return [_scrollPager viewWithTag:_current_page];
}
- (void)resetScrollerAtViewIndex:(NSInteger)index
{
UIScrollView *scrollView = [_scrollPager viewWithTag:index];
CGFloat zoomScale = scrollView.zoomScale;
if(zoomScale != 1.0)
[scrollView setZoomScale:1 animated:YES];
}
Edit for zoom out when return to previous or next page
just replace the below method
- (void)resetScrollerAtViewIndex:(NSInteger)index
{
//CGFloat zoomScale = 1.0;
UIScrollView *scrollView = [_scrollPager viewWithTag:index];
CGRect rectToZoomTo = CGRectZero;
rectToZoomTo = [self zoomRectForScrollView:scrollView withScale:1 withCenter:self.view.center];
[scrollView zoomToRect:self.view.bounds animated:YES];
[scrollView setContentOffset:CGPointZero];
[scrollView setContentSize:self.view.bounds.size];
}

Scrolling to specific page using pageControl and ScrollView ios

I know this question has been asked earlier but i am not getting any specific answer to my problem. I am using page control and scrollView to add view controllers and then showing all the pages using swipe. I need to redirect to a particular page on button click. I tried scrollView SetcontentOffet and every other possiblities.
-(void)ScrollToPage:(int)page
{
UIViewController *controller = [self.childViewControllers objectAtIndex:page];
if (controller.view.superview == nil)
{
CGRect frame = self.scrollView.frame;
if (frame.size.width == 0)
{
frame.size.width = self.view.frame.size.width;
frame.size.height = self.view.frame.size.height;
}
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
controller.view.frame = frame;
[scrollView setContentOffset:CGPointMake(frame.origin.x, frame.origin.y) animated:YES];
self.pageControl.currentPage = page;
[self centerScrollViewContents];
[self.scrollView setContentOffset:CGPointMake(frame.origin.x, frame.origin.y)];
[self.scrollView scrollRectToVisible:frame animated:YES];
[self.scrollView addSubview:controller.view];
}
}
I assume that your pages are using your device width closely. Just follow the below steps.
- (void)viewWillAppear:(BOOL)animated {
self.myCurrentPage = 0;
[self setScrollViewPages];
self.scrollView.delegate = self;
}
- (void)setScrollViewPages {
for (int i = 0; i < numberOfPages; i++) {
UIView *myPageView = [[UIView alloc]initWithFrame:(CGRect) {self.view.frame.size.width * i
+ 10.0f,10.0f,self.view.frame.size.width - 20.0f , self.scrollView.frame.size.height-20.0f}];
myPageView.backgroundColor = [UIColor greenColor];
[self.scrollView addSubview:myPageView];
}
}
On Button Clicked
- (IBAction)buttonClicked:(id)sender {
//Pass the requried page, by default I'm passing 4
self.myCurrentPage = 4;
[self updateMyScrollView];
}
And the respective scroll view setting is
- (void)updateMyScrollView {
[self.scrollView setContentOffset:CGPointMake(self.view.frame.size.width *self.myCurrentPage, 0) animated:YES];
self.pageControl.currentPage = self.myCurrentPage;
}
Additionally, your scrollview delegate would be like this...
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{
int pageWidth = self.view.frame.size.width ;
int pageX = self.myCurrentPage*pageWidth - scrollView.contentInset.left;
if (targetContentOffset->x<pageX) {
if (self.myCurrentPage>0) {
self.myCurrentPage--;
}
}
else if(targetContentOffset->x>pageX){
if (self.myCurrentPage < numerOfPages) {
self.myCurrentPage++;
}
}
targetContentOffset->x = self.myCurrentPage*pageWidth-scrollView.contentInset.left;
DLog(#"%ld %d", (long)self.myCurrentPage, (int)targetContentOffset->x);
self.pageControl.currentPage = self.myCurrentPage;
}
Hope this helps....

How can I make UIScrollView/UIPageControl infinite?

I have created a simple image scrolling with UIPageControl and UIScrollView, I have three pages ! so what I need is when user scrolls page 0 to left , actually scroll should move to the page 3 and vice versa . I have checked Apple sample code but it was so complicated !, here is my codes :
- (void)setupScrollView {
_pageControl.currentPage = 0;
_pageControl.numberOfPages = 3;
[_scrollView setContentSize:CGSizeMake(_scrollView.frame.size.width * _pageControl.numberOfPages, _scrollView.frame.size.height)];
_scrollView.delegate = self;
[self createPageWithImage:_image1 forPage:0];
[self createPageWithImage:_image2 forPage:1];
[self createPageWithImage:_image3 forPage:2];
}
- (void)createPageWithImage:(UIImageView *)frameImage forPage:(int)page
{
UIView *newView = [[UIView alloc] initWithFrame: CGRectMake(_scrollView.frame.size.width * page, 0, _scrollView.frame.size.width, _scrollView.frame.size.height)];
[newView addSubview: frameImage];
[_scrollView addSubview: newView];
}
- (void)scrollViewDidScroll: (UIScrollView *) sView
{
CGFloat offset = _scrollView.contentOffset.x;
CGFloat pageSize = _scrollView.frame.size.width;
int page = floor((offset + (pageSize/2)) / pageSize);
_pageControl.currentPage = page;
}
- (IBAction)changeThePage
{
CGRect pageRect = CGRectMake(_pageControl.currentPage * _scrollView.frame.size.width, 0, _scrollView.frame.size.width, _scrollView.frame.size.height);
[_scrollView scrollRectToVisible: pageRect animated: YES];
}
Adding the methods which I have changed. I have commented wherever necessary.
- (void)setupScrollView {
_pageControl.currentPage = 0;
_pageControl.numberOfPages = 3 ;
//Add 2 more pages.
[_scrollView setContentSize:CGSizeMake(_scrollView.frame.size.width * (_pageControl.numberOfPages + 2), _scrollView.frame.size.height)];
_scrollView.delegate = self;
// Seriously recommend this for this type of apps.
_scrollView.pagingEnabled = YES;
// Do not instantiate imageviews. Send only image names as string.
// Add last image at beginning of scroll view.
[self createPageWithImageName:#"imageName3" forPage:0];
// Increase page number of existing images.
[self createPageWithImageName:#"imageName1" forPage:1];
[self createPageWithImageName:#"imageName2" forPage:2];
[self createPageWithImageName:#"imageName3" forPage:3];
//Add first image at end of scroll view
[self createPageWithImageName:#"imageName1" forPage:4];
// Show first image but present in second page.
[_scrollView setContentOffset:CGPointMake(_scrollView.frame.size.width, 0) animated:NO];
}
// Instead of sending image views, send image name. Create image view inside this method.
// This is because, since we are adding two more images, separate image view needs
// to be created. Otherwise, same image view will be used and one added at the end
// will be used as the frame of the image.
- (void)createPageWithImageName:(NSString *)imageName forPage:(int)page
{
UIView *newView = [[UIView alloc] initWithFrame: CGRectMake(_scrollView.frame.size.width * page, 0, _scrollView.frame.size.width, _scrollView.frame.size.height)];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:newView.bounds];
imageView.image = [UIImage imageNamed:imageName];
[newView addSubview: imageView];
[_scrollView addSubview: newView];
}
- (void)scrollViewDidScroll: (UIScrollView *) sView
{
CGFloat offset = _scrollView.contentOffset.x;
CGFloat pageSize = _scrollView.frame.size.width;
int page = floor((offset + (pageSize/2)) / pageSize);
if (page == 0) {
page = _pageControl.numberOfPages - 1;
}
else if (page == _pageControl.numberOfPages + 1) {
page = 0;
}
else {
page = page - 1;
}
_pageControl.currentPage = page;
// If present in scroll view's first page, move it to second last page
if (offset < pageSize) {
[_scrollView setContentOffset:CGPointMake(pageSize * 3 + offset, 0) animated:NO];
}
// If present in scroll view's last page, move it to second page.
else if (offset >= pageSize * (_pageControl.numberOfPages + 1)) {
CGFloat difference = offset - pageSize * _pageControl.numberOfPages;
[_scrollView setContentOffset:CGPointMake(difference, 0) animated:NO];
}
}
The method of changeThePage is not needed for this code.
Hope this answer helps you.

Zooming UIImageView in a UIScrollView acts weirdly

I have the following problem, guys. I have an app that is pretty much like Apple's PhotoScroller. I want to jump from image to image by swiping the screen. I can do that, but I can't zoom the images. Here's the problem - I have an array with images. If the array has only one object inside, there's no problem with zooming. But if there are more images in the array, they acts weirdly when I try to zoom. The image is not being zoomed and it goes where it wants off the screen. Here is my code:
int pageWidth = 1024;
int pageHeight = 768;
int counter = 0;
self.view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, pageWidth, pageHeight)];
CGRect containerFrame = self.view.frame;
scrollView = [[UIScrollView alloc] initWithFrame:containerFrame];
[self.view addSubview:scrollView];
NSMutableArray *all = [[NSMutableArray alloc] init];
[all addObject:[UIImage imageNamed:#"222.jpg"]];
CGSize scrollSize = CGSizeMake(pageWidth * [all count], pageHeight);
[scrollView setContentSize:scrollSize];
for (UIImage *image in all)
{
UIImage *pageImage = [[UIImage alloc] init];
pageImage = [all objectAtIndex:counter];
CGRect scrollFrame = CGRectMake(pageWidth * counter, 0, pageWidth, pageHeight);
miniScrollView = [[UIScrollView alloc] initWithFrame:scrollFrame];
[scrollView addSubview:miniScrollView];
CGSize miniScrollSize = CGSizeMake(pageImage.size.width, pageImage.size.height);
[miniScrollView setContentSize:miniScrollSize];
UIImageView *tempImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, pageImage.size.width, pageImage.size.height)];
tempImageView.image = [all objectAtIndex:counter];
self.imageView = tempImageView;
miniScrollView.maximumZoomScale = 3.0;
miniScrollView.minimumZoomScale = 1.0;
miniScrollView.clipsToBounds = YES;
miniScrollView.delegate = self;
miniScrollView.showsHorizontalScrollIndicator = NO;
miniScrollView.showsVerticalScrollIndicator = NO;
miniScrollView.bouncesZoom = YES;
[miniScrollView addSubview:imageView];
counter ++;
}
[scrollView setPagingEnabled:YES];
[scrollView setScrollEnabled:YES];
}
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return imageView;
}
Do you have any ideas what's wrong? Because I am trying to get this work almost 2 weeks.
I also worked on such sort of App. The first thing that you can do is to take a separate subclass of your ScrollView so that all the paging and zooming operations can be handled easily. In your scrollView Class, You can take reference from the following code snippet.
#interface PhotoScrollView : UIScrollView<UIScrollViewDelegate,UIGestureRecognizerDelegate>
{
int finalPhotoWidth;
int finalPhotoHeight;
}
// to contain image
#property (strong, nonatomic) UIImageView *imageView;
- (id)initWithFrame:(CGRect)frame andImage:(UIImage *)photo
{
self = [super initWithFrame:frame];
if (self)
{
// Initialization code
[self initializeScrollViewWithImage:photo];
//setting gesture recognizer for single tap
UITapGestureRecognizer *singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(scrollViewSingleTapped:)];
singleTapRecognizer.delegate = self;
singleTapRecognizer.numberOfTapsRequired = 1;
[self addGestureRecognizer:singleTapRecognizer];
//setting gesture recognizer for Double tap
UITapGestureRecognizer *doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(scrollViewDoubleTapped:)];
doubleTapRecognizer.delegate = self;
doubleTapRecognizer.numberOfTapsRequired = 2;
[self addGestureRecognizer:doubleTapRecognizer];
[singleTapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];
singleTapActivated = FALSE;
self.backgroundColor = [UIColor blackColor];
self.minimumZoomScale = 1.0f;
self.maximumZoomScale = 15.0f;
self.zoomScale = 1.0f;
self.delegate = self;
}
return self;
}
//for sizing the frame by giving height and width
-(void)initializeScrollViewWithImage:(UIImage*)photo
{
finalPhotoWidth = photo.size.width;
finalPhotoHeight = photo.size.height;
//Pre-checking of frame and setting the height and width accordingly
if (finalPhotoHeight > self.frame.size.height)
{
// if photo height is bigger than frame height, re-adjust the photo height and width accordingly
finalPhotoHeight = self.frame.size.height;
finalPhotoWidth = (photo.size.width/photo.size.height) * finalPhotoHeight;
}
if (finalPhotoWidth > self.frame.size.width)
{
// if photo width is bigger than frame width, re-adjust the photo height and width accordingly
finalPhotoWidth = self.frame.size.width;
finalPhotoHeight = (photo.size.height/photo.size.width) * finalPhotoWidth;
}
if (finalPhotoHeight < self.frame.size.height && finalPhotoWidth < self.frame.size.width)
{
// if the photo is smaller than frame, increase the photo width and height accordingly
finalPhotoWidth = self.frame.size.width;
finalPhotoHeight = self.frame.size.height;
}
//initialising imageView with the thumbnail photo
self.imageView = [[UIImageView alloc] initWithImage:photo];
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
//setting frame according to the modified width and height
if(!isnan(finalPhotoWidth) && !isnan(finalPhotoHeight))
{
self.imageView.frame = CGRectMake( (self.frame.size.width - finalPhotoWidth) / 2, (self.frame.size.height - finalPhotoHeight)/2, finalPhotoWidth, finalPhotoHeight);
}
// setting scrollView properties
self.contentSize = self.imageView.frame.size;
// add image view to scroll view
[self addSubview:self.imageView];
}
//to deny the simultaneous working of single and double taps
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return NO;
}
// Gesture handleer for single tap gesture
-(void)scrollViewSingleTapped:(UITapGestureRecognizer *)recognizer
{
if(!singleTapActivated)
{
//do as per requirement
singleTapActivated = TRUE;
}
else
{
//do as per requirement
singleTapActivated = FALSE;
}
}
//for zooming after double tapping
- (void)scrollViewDoubleTapped:(UITapGestureRecognizer*)recognizer
{
//to check whether image is zoomed
if (self.zoomScale != 1.0f)
{
//if image is zoomed, then zoom out
[self setZoomScale:1.0 animated:YES];
self.imageView.frame = CGRectMake( (self.frame.size.width - finalPhotoWidth) / 2, (self.frame.size.height - finalPhotoHeight)/2, finalPhotoWidth, finalPhotoHeight);
[self.observer photoZoomStopped];
}
else
{
// get the point of image which is double tapped
CGPoint pointInView = [recognizer locationInView:self.imageView];
// Get a zoom scale that's zoomed in slightly, capped at the maximum zoom scale specified by the scroll view
CGFloat newZoomScale = self.zoomScale * 4.0f;
newZoomScale = MIN(newZoomScale, self.maximumZoomScale);
// Figure out the rect we want to zoom to, then zoom to it
CGSize scrollViewSize = self.imageView.frame.size;
CGFloat w = scrollViewSize.width / newZoomScale;
CGFloat h = scrollViewSize.height / newZoomScale;
CGFloat x = pointInView.x - (w / 2.0f);
CGFloat y = pointInView.y - (h / 2.0f);
CGRect rectToZoomTo = CGRectMake(x, y, w, h);
[self zoomToRect:rectToZoomTo animated:YES];
}
}
// To re-center the image after zooming in and zooming out
- (void)centerScrollViewContents
{
CGSize boundsSize = self.bounds.size;
CGRect contentsFrame = self.imageView.frame;
if (contentsFrame.size.width < boundsSize.width)
{
contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width) / 2.0f;
}
else
{
contentsFrame.origin.x = 0.0f;
}
if (contentsFrame.size.height < boundsSize.height)
{
contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height) / 2.0f;
}
else
{
contentsFrame.origin.y = 0.0f;
}
self.imageView.frame = contentsFrame;
}
//for zooming in and zooming out
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
if (self.zoomScale > 1.0f)
{
[self.observer photoZoomStarted];
[self centerScrollViewContents];
}
else
{
self.bouncesZoom = NO;
[self.observer photoZoomStopped];
// for zooming out by pinching
[self centerScrollViewContents];
}
// The scroll view has zoomed, so we need to re-center the contents
}
- (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
Please let me know if it helps. Thanks :)

UIImageView is cut off on right side within PageControl after zooming

my image is cut off on the right side after zooming in. if i don't set the offset with cgrect make, then it is not cut off, but i want my image to be centered on the screen. how can i have my image centered and not cut off the right portion after zooming?
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = [UIColor grayColor];
UIScrollView *mainScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
mainScrollView.pagingEnabled = YES;
mainScrollView.showsHorizontalScrollIndicator = NO;
mainScrollView.showsVerticalScrollIndicator = NO;
CGRect innerScrollFrame = mainScrollView.bounds;
for (NSInteger i = 0; i < 2; i++) {
UIImageView *imageForZooming = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:#"page%d", i + 1]]];
imageForZooming.tag = VIEW_FOR_ZOOM_TAG;
imageForZooming.frame = CGRectMake(50, 0, imageForZooming.bounds.size.width, imageForZooming.bounds.size.height);
UIScrollView *pageScrollView = [[UIScrollView alloc] initWithFrame:innerScrollFrame];
pageScrollView.minimumZoomScale = 0.5f;
pageScrollView.maximumZoomScale = 1.0f;
pageScrollView.contentSize = imageForZooming.bounds.size;
pageScrollView.delegate = self;
[pageScrollView addSubview:imageForZooming];
[mainScrollView addSubview:pageScrollView];
if (i < 1) {
innerScrollFrame.origin.x += innerScrollFrame.size.width;
}
pageScrollView.zoomScale = 0.5f;
}
mainScrollView.contentSize = CGSizeMake(innerScrollFrame.origin.x + innerScrollFrame.size.width, mainScrollView.bounds.size.height);
[self.view addSubview:mainScrollView];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return [scrollView viewWithTag:VIEW_FOR_ZOOM_TAG];
}
EDIT: here is my view hierarchy
View
mainScrollView
innerScrollFrame
pageScrollView
imageForZooming
innerScrollFrame
pageScrollView
imageForZooming
For anyone else having the same problem in the future, what I did was add the following UIScrollViewDelegate protocol:
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
UIView *subView = [scrollView.subviews objectAtIndex:0];
CGFloat offsetX = (scrollView.bounds.size.width > scrollView.contentSize.width) ? (scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5 : 0.0;
CGFloat offsetY = (scrollView.bounds.size.height > scrollView.contentSize.height) ? (scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5 : 0.0;
subView.center = CGPointMake(scrollView.contentSize.width * 0.5 + offsetX,
scrollView.contentSize.height * 0.5 + offsetY);
}
i found the answer here: Center content of UIScrollView when smaller
so that the image would be centered after zooming instead of applying the offset that was initially applied. worked like a charm. now when I zoom, none of my image is cut off on either page control, and I can center the image at the beginning of the view.

Resources