How to create view based animation in objective c? - ios

I have to add the following animation in my iOS app, I have used a scroll bar along with UITableView and achieved the top and bottom animation, but I'm still stuck at the middle animation part where the 4 UIViews come in a single horizontal line. Any suggestions?
http://www.image-maps.com/m/private/0/af8u4ulika9siddnf6k6hhrtg2_untitled-2.gif
Code:-
#implementation AnimatedView {
UIScrollView *mainScroll;
UIScrollView *backgroundScrollView;
UILabel *_textLabel;
UITableView *_commentsTableView;
UIView *menuView;
UIView *_commentsViewContainer;
UIView *fadeView;
UIImageView *imageView;
NSMutableArray *comments;
}
- (id)init {
self = [super init];
if (self) {
_mainScrollView = [[UIScrollView alloc] initWithFrame:[UIApplication sharedApplication].keyWindow.frame];
self.view = _mainScrollView;
_backgroundScrollView = [[UIScrollView alloc] initWithFrame:HEADER_INIT_FRAME];
imageView = [[UIImageView alloc] initWithFrame:HEADER_INIT_FRAME];
fadeView = [[UIView alloc] initWithFrame:imageView.frame];
_textLabel = [[UILabel alloc] initWithFrame:CGRectMake(10.0f, 100.0f, 150.0f, 25.0f)];
menuView = [[UIView alloc] initWithFrame:CGRectMake(0,_textLabel.frame.size.height+150, self.view.frame.size.width+30, 180)];
[_backgroundScrollView addSubview:imageView];
[_backgroundScrollView addSubview:fadeView];
[_backgroundScrollView addSubview:menuView];
[_backgroundScrollView addSubview:_textLabel];
_commentsViewContainer = [[UIView alloc] init];
_commentsTableView = [[UITableView alloc] init];
_commentsTableView.scrollEnabled = NO;
_commentsTableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
[self.view addSubview:_backgroundScrollView];
[_commentsViewContainer addSubview:_commentsTableView];
[self.view addSubview:_commentsViewContainer];
// fake data!
comments = [#[#"Array for tableview"] mutableCopy];
}
return self;
}
#pragma mark Scroll
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat delta = 0.0f;
CGRect rect = HEADER_INIT_FRAME;
// Here is where I do the "Zooming" image and the quick fade out the text and toolbar
if (scrollView.contentOffset.y < 0.0f) {
delta = fabs(MIN(0.0f, _mainScrollView.contentOffset.y));
_backgroundScrollView.frame = CGRectMake(CGRectGetMinX(rect) - delta / 2.0f, CGRectGetMinY(rect) - delta, CGRectGetWidth(rect) + delta, CGRectGetHeight(rect) + delta);
[_commentsTableView setContentOffset:(CGPoint){0,0} animated:NO];
} else {
delta = _mainScrollView.contentOffset.y;
_textLabel.alpha = 1.0f;
CGFloat backgroundScrollViewLimit = _backgroundScrollView.frame.size.height - kBarHeight;
// Here I check whether or not the user has scrolled passed the limit where I want to stick the header, if they have then I move the frame with the scroll view
// to give it the sticky header look
if (delta > backgroundScrollViewLimit) {
_backgroundScrollView.frame = (CGRect) {.origin = {0, delta - _backgroundScrollView.frame.size.height + kBarHeight}, .size = {self.view.frame.size.width, HEADER_HEIGHT}};
_commentsViewContainer.frame = (CGRect){.origin = {0, CGRectGetMinY(_backgroundScrollView.frame) + CGRectGetHeight(_backgroundScrollView.frame)}, .size = _commentsViewContainer.frame.size };
_commentsTableView.contentOffset = CGPointMake (0, delta - backgroundScrollViewLimit);
CGFloat contentOffsetY = -backgroundScrollViewLimit * kBackgroundParallexFactor;
[_backgroundScrollView setContentOffset:(CGPoint){0,contentOffsetY} animated:NO];
}
else {
_backgroundScrollView.frame = rect;
_commentsViewContainer.frame = (CGRect){.origin = {0, CGRectGetMinY(rect) + CGRectGetHeight(rect)}, .size = _commentsViewContainer.frame.size };
[_commentsTableView setContentOffset:(CGPoint){0,0} animated:NO];
[_backgroundScrollView setContentOffset:CGPointMake(0, -delta * kBackgroundParallexFactor)animated:NO];
}
}
}
- (void)viewDidAppear:(BOOL)animated {
_mainScrollView.contentSize = CGSizeMake(CGRectGetWidth(self.view.frame), _commentsTableView.contentSize.height + CGRectGetHeight(_backgroundScrollView.frame));
}

You don't need any scrollview to implement this really. All you need is 1 UITableView with 2 sections. First section has a single empty element (but set the row height to 0), and enable the header for both sections. You can use UIViews for the headerViews. Then, you only need to change the header height (with icon positioning) based on tableview Delegate scrollViewDidScroll. scrollViewDidScroll is also a delegate of UITableView since one of TableView's element inherits from UIScrollView.

Related

iOS Layer animation with auto layout

I have a simple container view(green) and two sub views(red and blue) as below.
The container view is not applying auto layout and I config its size & location by frame.
While the sub views are applying auto layout(see code below)
#implementation XXView {
UIView *_leftView;
UIView *_rightView;
}
- (instancetype)init {
self = [super initWithFrame:CGRectZero];
if (self) {
[self setupViewHierarchy];
[self setupConstraints];
}
return self;
}
- (void)setupViewHierarchy {
_leftView = [[UIView alloc] init];
_leftView.backgroundColor = UIColor.redColor;
_leftView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_leftView];
_rightView = [[UIView alloc] init];
_rightView.backgroundColor = UIColor.blueColor;
_rightView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_rightView];
self.backgroundColor = UIColor.greenColor;
}
- (void)setupConstraints {
[NSLayoutConstraint activateConstraints:#[
[_leftView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:10],
[_leftView.topAnchor constraintEqualToAnchor:self.topAnchor],
[_leftView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
[_leftView.widthAnchor constraintEqualToConstant:50],
[_rightView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-10],
[_rightView.topAnchor constraintEqualToAnchor:_leftView.topAnchor],
[_rightView.bottomAnchor constraintEqualToAnchor:_leftView.bottomAnchor],
[_rightView.widthAnchor constraintEqualToAnchor:_leftView.widthAnchor],
]];
}
...
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
XXView *tv = [[XXView alloc] init];
CGFloat width = self.view.bounds.size.width;
tv.frame = CGRectMake(50, 400, width-100, 100);
[self.view addSubview:tv];
self.tv = tv;
}
Then I would like to animate the container's width change by using the CABasicAnimation as below:
- (void)startAnimation {
[CATransaction begin];
CGFloat width = self.bounds.size.width;
CABasicAnimation *widthAnimation = [CABasicAnimation animationWithKeyPath:#"bounds.size.width"];
widthAnimation.fromValue = #(width/2);
widthAnimation.toValue = #(width);
widthAnimation.duration = 1;
[self.layer addAnimation:widthAnimation forKey:#"123"];
[CATransaction commit];
}
However, the animation is not as I would expect. I would expect the left view moves as the container's leading side and the right view does as the trailing side.
What I see is, the green view expands as expected and the left view moves as green view's leading side. However, the right view is always keeping the same distance to left view. Below is the screenshot taken at the beginning of the animation.
Why the animation is not working as expected?
The problem is that your CABasicAnimation is modifying the bounds of the layer ... but as far as auto-layout is concerned that does not change the width of the view.
It's not really clear what your goal is here, but if you change your animation method to this it might get you on your way:
- (void)startAnimation {
CGRect f = self.frame;
CGFloat fw = f.size.width;
f.size.width = fw / 2;
self.frame = f;
[self layoutIfNeeded];
f.size.width = fw;
[UIView animateWithDuration:1.0 animations:^{
self.frame = f;
[self layoutIfNeeded];
}];
}

UIImageview not showing after being added to another subview which is UIScrollview

I am creating a view controller in code only, NO .xib or storyboard.
I have many other subviews added to the view, which are added in a method (void)loadView and their frames are initialised in the (id)init method as shown below
-(id)init{
bottomClinkRect = CGRectMake(playersBoardRect.origin.x + (playersBoardWidth * 0.320),
playersBoardRect.origin.y + playersBoardHeight - playerBottomImageRect.size.height - (playersBoardHeight * 0.038),
playersBoardWidth * 0.680,
playersBoardHeight * 0.038);
}
- (void)loadView {
bottomClink = [[UIScrollView alloc]initWithFrame:bottomClinkRect];
[bottomClink setScrollEnabled:YES];
bottomClink.contentSize = CGSizeMake(bottomClink.frame.size.height,bottomClink.frame.size.height);
[contentView addSubview:bottomClink];
}
I create empty scrollview and then based on user actions on screen I am trying to add one imageView per time to the scrollview using the following method:
-(void)reloadCollections:(NSNotification *)notification
{
UIImage *latestPieceCaptured = [gameController capturedBlackPiecesImages].lastObject;
[whitePlayerCaptures addObject:latestPieceCaptured];
NSInteger newNumberOfViews = whitePlayerCaptures.count;
CGFloat xOrigin = (newNumberOfViews - 1) * bottomClink.frame.size.height;
CGRect imageRect = CGRectMake(bottomClink.frame.origin.x + xOrigin,
bottomClink.frame.origin.y,
bottomClink.frame.size.height, //the width is taken from the height
bottomClink.frame.size.height); // the height
UIImageView *image = [[UIImageView alloc] initWithFrame:imageRect];
image.backgroundColor = [UIColor blackColor];
image.image = latestPieceCaptured;
image.contentMode = UIViewContentModeScaleAspectFit;
//set the scroll view content size
bottomClink.contentSize = CGSizeMake(bottomClink.frame.size.height * newNumberOfViews,
bottomClink.frame.size.height);
[bottomClink addSubview:image];
}
My problem is that the scrollview is added to the main view but the imageview(s) are not showing up.
I have debugged it and the scrollview has the subviews added and they have frame size and all, but not showing on the screen. I have tried so many variations but nothing has worked so far.
Thanks in advance for any links or advice.
That works for me:
- (void)addImagesToScrollView {
[self.scrollViewOutlet setAlwaysBounceVertical:NO];
_scrollViewOutlet.delegate = self;
for (int i = 0; i < thumbnailPreview.count; i++) {
CGFloat xOrigin = i * self.scrollViewOutlet.frame.size.width;
UIImageView *image = [[UIImageView alloc] initWithFrame:
CGRectMake(xOrigin, 0,
self.scrollViewOutlet.frame.size.width,
self.scrollViewOutlet.frame.size.height)];
image.image = [UIImage imageNamed: [thumbnailPreview objectAtIndex:i]];
image.contentMode = UIViewContentModeScaleAspectFill;
image.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
image.clipsToBounds = YES;
[self.scrollViewOutlet addSubview:image];
}
//set the scroll view content size
self.scrollViewOutlet.contentSize = CGSizeMake(self.scrollViewOutlet.frame.size.width *
thumbnailPreview.count,
self.scrollViewOutlet.frame.size.height);
}
And call it in
- (void)viewDidAppear:(BOOL)animated

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