iOS 6 Autolayout - ScrollView with embedded ImageView not zooming properly - ios

I am trying to setup a simple view that displays an image and allows users to zoom in/out and pan the image as they desire.
I have autoLayout enabled and the view consists of a UIScrollView with an embedded UIImageView.
Both views are sized to the entire screen.
I used the logic and code from Apple's ScrollViewSuite (the "1_TapToZoom" sample) and everything seems correct. However, when pinching the view, the ScrollView/ImageView gets all distorted and doesn't respond properly. Hard to explain the behavior, but lets just call it "funky". The size and aspect changes in no consistent manner.
My GUESS is that this has to do with autolayout constraints.
Does anyone have some suggestions/fixes for this?

The issues that occurs is the changing of location of the imageview during the zoom process. The origin location of the imageview will change to be a negative value during the zoom. I believe this is why the jerky movement occurs. As well, after the zoom is complete the imageView is still in the wrong location meaning that scrolls will appear to be offset.
If you implement -(void) scrollViewDidZoom:(UIScrollView *)scrollView and log the frame of the UIImageView during this time you can see its origin changing.
I ended up making things work out by implementing a strategy like this: https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/ch20p573scrollViewAutoLayout/ch20p573scrollViewAutoLayout/ViewController.m
And in addition changing the frame of the contentView while zooming
-(void) scrollViewDidZoom:(UIScrollView *)scrollView {
CGRect cFrame = self.contentView.frame;
cFrame.origin = CGPointZero;
self.contentView.frame = cFrame;
}

Related

UIView CGAffineTransform scale issue (autolayout issue?)

I am trying to apply a simple CGAffineTransform to an imageView by scaling to 0, but for some reason the frame of the imageView is getting screwed up just before the animation starts. It appears as though autolayout is applying to the shrunken view. I don't want that at all. I want the view to remain "relatively" where it was and just visually shrink to its center, but because the view is tied to the top and right of its containing view, it is being moved.
What I want is for it to shrink into its center and disappear, but just before it starts, the frame of the imageView is jumping to the top-right of its container (it seems as though iOS is calculating its size after the animation and using that to reposition it before the animation starts). After it jumps there, the animation works properly with respect to itself, with the view shrinking relative to its center, but I want to avoid it moving in the first place.
This is all taking place inside a UITableViewCell that is managed by autolayout, so I'm guessing this has something to do with autolayout and <understatement> would not be the first time autolayout has gotten in my way </understatement>.
Is there any way to prevent autolayout from affecting the transform?

UIScrollView Pinch and Zoom ONLY on center?

Been trying to figure this out for days.
Let's say I have an imageView embedded in a UISCrollView and everything is implemented correctly.
How it is currently functioning: When the user pinches and zooms on the top right of the image, it will zoom towards the top right area.
How I want it: I want the image to zoom ONLY on the center of the UIView, regardless on where the user pinches on the photo.
I was thinking of somehow intercepting the pinch gesture recognizer and modifying it so that the pinch locations are always in the center of the screen, but not sure if that's possible. Any ideas? Thanks!
If you want the zoom to happen only at centre, use scrollViewDidZoom delegate method.
--CODE--
-(void)scrollViewDidZoom:(UIScrollView *)scrollView{
CGFloat width = scrollView.contentSize.width/2;
width =width-width/scrollView.zoomScale;
CGFloat height = scrollView.contentSize.height/2;
height =height-height/scrollView.zoomScale;
scrollView.contentOffset = CGPointMake(width, height);
}
As I see it, you have many options. I will state the one that I find the easiest (will delve deeper if it does not work).
Subclass the UIScrollView and override it's layoutSubviews method, and use it to set the visibleRect of the scroll view to the center of the scroll view (which happens to be the center of the image, judging by your screenshot). It will maintain it's zoomLevel so you do not need to alter it.

UIScrollView, sliding, zooming

I have an app which has a uiscrollview, which in turn has two uiimageviews.
The scrollview works fine in sliding between both imageviews, by making the content size twice the width. like so
[self.scrollView setContentSize:CGSizeMake(self.scrollView.frame.size.width * 2, self.scrollView.frame.size.height)];
Now the client wants the user to be able to zoom into any image in those two images. He does not want another modal view with the selected picture zoomed in, but rather on the same uiscrollview he wants this to happen. Is this doable? or a good Idea?
The problem I am having is that when I implement the zooming logic ( implementing the delegate
UIScrollViewDelegate
the moment I set the value of
self.scrollView.zoomScale
I end up calling this method
- (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return [self getCurrentVisibleImage];
}
And with that happening, I end up with the UIscrollview that after zooming back to the normal size of the image, the scrollview simply doesn't slide left or right?
Any help is appreciated.
Answer was simple, I was manipulating contentsize and not setting it properly. that fixed it.

Resize content of UIScrollView when zooming

I know there is many topics for this subject but I didn't found a good solution for my problem.
I have a UIScrollView with an image and other components added as subviews.
I just want to know the good way to resize the components into in real time when I zoom.
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
// Resizing image and other components
}
EDIT : I would like the impression that the components inside the scroll view keep the same size when I zoom. I don't want to they become bigger or smaller during zooming.
EDIT : Here is the hierarchy of my UIViewController
View
ScrollView
Main view
Image view
Drawing view (UIView with components like UILabel, other UIViews, etc...)
Thanks a lot !
I would leave the scale of UIScrollView as it is and reach the goal with the help of subview (adjusting its size, not scrollView's), where I would place all the subviews and the images you work with.
So it would be something like:
yourView.transform = CATransform3DMakeScale(newScale, newScale, 1.0);
where yourView is the main (only) subview of scrollView. Then I would recalculate the size of the yourView with new scale and set it to scrollView's contentSize parameter so that you could actually scroll the enlarged content, not only see it truncated.
The only thing is that in this case you should use the callback other than scrollViewDidZoom: I guess.
P.S. Changing UIView's transform parameter you don't need to bother about subviews' scale: CoreAnimation does everything for you.

How can I let UIScrollView (pagingEnabled) to move 1.2 page each time?

Ok. here is the story:
I have a UIWebView in full screen, width = 768
It loads several images and those images are in one line, which means the UIWebView will scroll only horizontally.
Now, I set the UIScrollView inside the UIWebView to pagingEnabled = YES. So the scroll on the UIWebView will move page by page.
The problem is that every image's width is about 900. I won't scale them down and if I scroll the UIWebView, from the 2nd page on, always 132points of previous image will show. This is not good for me.
So how can I manipulate the UIWebView or the UIScrollView inside the UIWebView so that each scroll will move a page of 900 points, if the view's frame width is 768?
The constraints are:
I can't change its contentSize
I can't change its bounds or frame
I say these constraints because UIWebView will change them on its own purpose when it loads contents.
Anyone would like to join this brain storming?
Thanks
I'm thinking you're going to need to set a UIScrollView delegate that tracks touches beginning and ending. More specifically, scrollViewDidEndDragging:willDecelerate is what I'm thinking you'll need to use, as it fires the instant a user lifts their hand from the device.
First, pagingEnabled=NO seems obvious, we're going to have to control our own paging. Which, I don't feel is too tough. Track the direction of the scrolling in scrollViewDidScroll:, so that we have some global set:
BOOL isGoingRight = YES or NO (NO means the last movement was to the left)
float PAGESIZE = 900.0;
Here's how my scrollview delegate method would look like that handles paging.
- (void) scrollViewDidEndDragging:(UIScrollView*)_scrollView willDecelerate:(BOOL)willDecelerate {
float offsetProportion = _scrollView.contentOffset.x/_scrollView.frame.size.width;
//depending upon our direction, round up or down
int page = isGoingRight? ceilf(offsetProportion): floorf(offsetProportion);
//manually finish the scroll
[_scrollView scrollRectToVisible:CGRectMake(page*PAGESIZE, 0, _scrollView.frame.size.width, _scrollView.frame.size.height) animated:YES];
}
I didn't test this, you may or may not need to disable touches at points.

Resources