UIScrollView Pinch and Zoom ONLY on center? - ios

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.

Related

UIScrollView over MKMapView

I'm trying to create a specific layout in an iOS App, where the "background" is a MKMapView and the overlay is a UIScrollView. The idea is that there are two screens, one with a map, and another with some additional information on. The user can scroll down to see this general information, and this view covers up the map and has a blurred background to create some depth.
Here's an image showing the layout:
As you can see, the map is fixed in its position. It will always be behind the content, even if you scroll. I want the map to respond to gestures, but only when used directly on the map. When the user "scrolls" over the bottom bar, I want the content to scroll up, revealing the second page which then covers the map.
I'm lost at what to do to achieve this. I tried putting the map on the original UIView and then covering it up with a scrollview, but this causes the map not to respond to gestures. I only want the UIScrollView to respond to gestures when it's on either the bottom bar, or the second page (each is its own separate view). Otherwise I want the Map to respond to the gestures.
I hope I managed to explain it well, if not, please do not hesitate to ask questions. I appreciate all help!
It sounds like you are adding a full screen UIScrollView on top of a MKMapView and the scrollview is picking up all the touches.
What you are asking about is not necessarily standard so there are multiple ways to implement it and you have to decide what works best for your use case.
Here is what I would do:
Use constraints on the scrollview to ensure that it is only covering the bottom bar area.
Make sure you can toggle the constant of the constraint controlling the scroll view's height (hook up an IBOutlet if you're using storyboard).
Add both a swipe gesture recognizer and a tap gesture recognizer that will fire toggleScrollViewFullScreen if recognized. Ensure that these recognizers can only be recognized while the scrollView is the bottom bar.
Have an X-out button display in the top corner while the scrollview is in full screen. This button can call toggleScrollViewFullScreen to dismiss the view back down.
Example toggleScrollViewFullScreen method:
//Toggle size of scroll view
- (void) toggleScrollViewFullScreen {
CGFloat bottomBarHeight = 100;
if (self.scrollViewHeightConstraint.constant > bottomBarHeight){
self.scrollViewHeightConstraint.constant = bottomBarHeight
}else {
self.scrollViewHeightConstraint.constant = self.view.bounds.size.height;
}
//Animate constraint change:
[UIView animateWithDuration:1 animations:^{
[self.view setNeedsUpdateConstraints];
[self.view setNeedsLayout];
}];
}

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.

UIScrollview sync a subview origin while zooming

i'm trying to develop a kind of custom map.
So I have a scrollview with zooming enabled.
This scrollview has an UIImageView as its subview that represent the map for the user.
I'd like the user to be able to "drop a pin" like in MapKit.
If I add the pin imageView to the map imageview, the pin image will zoom according to the scrollview zoom, which is not what I want.
I'd like to achieve the same result as in the MapKit Mapview.
The pin should move around when the user pan or zoom, but its image should not become smaller or bigger.
There's a simple way to do this without becoming crazy with math speculations over zoomscale and contentoffset?
Thanks a lot, everybody.
This is more of a guess than anything, but adding the pin's layer as a sublayer of the image view seems like the way to go about doing this.
I did it.
All I had to do was add the pin to the map imageview.
After that on the scrollView delegate, i adjusted the pin scale according to the scrollview zoomscale like this:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
_redPin.transform = CGAffineTransformMakeScale(1 / scrollView.zoomScale, 1 / scrollView.zoomScale);
}

iOS 6 Autolayout - ScrollView with embedded ImageView not zooming properly

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;
}

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