Why is UIScrollView's contentSize adjusted when zooming? - ios

With the code below, I see a red square appear which I can scroll around (because scrollview's content is 4x screen).
But once I start zooming out (scale < 1.0), the scrollview's contentSize immediately jumps to scale times the iPad's screen size. For example:
0.985783 757.081249 1009.441665
After which I cannot move the square around anymore. I can only move the square when scale get's above 1.0; in which case the scroll indicators show that the contentSize is still scale times screen size.
Another effect is that when zooming out below 1.0, the red square moves toward the top-left corner normally by zooming out. However, after I release the screen (without any further zooming), it moves even further to the corner. EDIT: This must be the rubber banding of the scrollview.
(The square itself does scale as expected.)
What I am missing here? Here's my view controller code:
- (void)viewDidLoad
{
[super viewDidLoad];
self.scrollView = [[UIScrollView alloc]initWithFrame:self.view.bounds];
self.scrollView.contentSize = CGSizeMake(self.view.bounds.size.width * 2, self.view.bounds.size.height * 2);
self.scrollView.backgroundColor = [UIColor colorWithWhite:0.5f alpha:1.0f];
self.scrollView.minimumZoomScale = 0.1f;
self.scrollView.maximumZoomScale = 4.0f;
self.scrollView.clipsToBounds = YES;
self.scrollView.delegate = self;
self.contentView = [[UIView alloc] initWithFrame:self.scrollView.bounds];
[self.scrollView addSubview:self.contentView];
[self.view addSubview:self.scrollView];
UIView* view = [[UIView alloc] initWithFrame:CGRectMake(400, 400, 100, 100)];
view.backgroundColor = [UIColor redColor];
[self.contentView addSubview:view];
}
#pragma UIScrollViewDelegate
- (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.contentView;
}
- (void)scrollViewDidEndZooming:(UIScrollView*)scrollView
withView:(UIView*)view
atScale:(double)scale
{
NSLog(#"%f %f %f", scale, self.scrollView.contentSize.width, self.scrollView.contentSize.height);
}

Related

How to convert frame from UIScrollView to UIView

I want to convert frame from UIScrollView to UIView, but not exaclty.
This is my code:
//Create UIScrollView addSubview self.view
scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
[scrollView setBouncesZoom:YES];
[scrollView setMinimumZoomScale:1];
[scrollView setZoomScale:4];
scrollView.delegate = self;
//create UIView overlay UIScrollView and addSubview self.view
overlayView = [[UIView alloc] initWithFrame:self.view.bounds];
overlayView.backgroundColor = [UIColor blueColor];
overlayView.alpha = 0.5;
[self.view addSubview:overlayView];
//create UIView addSubView overlayView, can move change postion
UIView *moveView = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 100, 100)];
moveView.backgroundColor = [UIColor redColor];
[overlayView addSubView:moveView];
If zoom in, zoom out scrollView, moveView change position by ratio when scrollView zoom in zoom out.
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale {
[scrollView setZoomScale:scale+0.01 animated:NO];
[scrollView setZoomScale:scale animated:NO];
CGRect visibleRect;
visibleRect.origin = scrollView.contentOffset;
visibleRect.size = CGSizeMake(scrollView.bounds.size.width * scrollView.zoomScale, scrollView.bounds.size.height * scrollView.zoomScale);
visibleRect.origin.x = 0;
visibleRect.origin.y = 0;
overlay.frame = visibleRect;
CGRect moveRect = moveView.frame;
moveRect.origin.x *= scrollView.zoomScale;
moveRect.origin.y *= scrollView.zoomScale;
moveRect.size.width *= scrollView.zoomScale;
moveRect.size.height *= scrollView.zoomScale;
moveView.frame = moveRect;
}
I cannot change postion moveView exactly when scrollView zoom in zoom out. Please help me resolve this issue.
First I'd say, you really need to be using autolayout for all this stuff. Or none of this will work if you rotate the device, or on different devices, etc. Just using frames to position views is just not the done way anymore. It will work to a degree though. Yes autolayout is a learning curve but you just need to know it and use it all the time.
But looking at the code there two issues stand out : at the start of the didEndZooming method, you set the scale twice, Im not sure why -
[scrollView setZoomScale:scale+0.01 animated:NO];
[scrollView setZoomScale:scale animated:NO];
Then also later, you set the origin of the visibleRect property twice in different ways :
visibleRect.origin = scrollView.contentOffset;
visibleRect.size = CGSizeMake(scrollView.bounds.size.width * scrollView.zoomScale, scrollView.bounds.size.height * scrollView.zoomScale);
visibleRect.origin.x = 0;
visibleRect.origin.y = 0;
Setting the x and y values there is the same as setting the origin to the scrollView.contentOffset - so first you set the origin to the content offset position, then to 0,0 - which doesnt make sense. Clearing up those problems might sort things out.

UIView +animateWithDuration: isn't animating a recently allocated view correctly

I'm attempting to allocate a webview with a specific frame, and then animate both its y position and height. When I do so, the webview instantly snaps to its "final" position, not animating the y, but it is animating the height.
Also, just so there's no confusion, I use UIView+Positioning (https://github.com/freak4pc/UIView-Positioning) to set my x,y,height, and width, instead of fiddling with the CGRects :)
Here is a screen capture of the animation, the issue is that the webview is instantly created at y=260/height=0px, where it should start at y=340/height=0px and transition to y=260 and height=maxHeight. y=340px is where the top and bottom split, and is where the "close" animation on the webview focuses to.
The code
for (PageViewController * page in pages) {
[page preFullscreen];
}
[UIView animateWithDuration:0.5f animations: ^() {
for (PageViewController * page in pages) {
[page fullScreen];
}
}];
...
- (void)preFullscreen {
_webView = [[UIWebView alloc] initWithFrame:CGRectMake(0.0f, 340.0f, 320.0f, 0.0f)];
_webView.delegate = self;
_webView.scrollView.bounces = NO;
_webView.scrollView.scrollEnabled = NO;
_webView.scalesPageToFit = YES;
_webView.backgroundColor = [UIColor whiteColor];
[_scrollView addSubview:_webView];
[_webView loadHTMLString:[entry storyHTML] baseURL:nil];
}
- (void)fullScreen {
_darkOverlayview.alpha = 0.0f;
_webView.y=260.0f;
_webView.height = [[UIScreen mainScreen] bounds].size.height - 260.0f;
_scrollView.delegate = hsVC;
_textareaView.hidden = YES;
_frontImage.height = 260.0f;
self.view.height = [[UIScreen mainScreen] bounds].size.height;
_scrollView.height = [[UIScreen mainScreen] bounds].size.height;
}
I think the problem is precisely that you are using the UIView+Positioning additions? Internally it ends up setting the frame multiple times within the animation block, so the start position is lost. Use the regular setFrame: to set the entire frame once per view in the animation block.
As for animating the UIWebView, I also recommend setting it to full height in preFullscreen (so that it's below the bottom edge of the screen) and only animating the y coordinate. In my experience resizing webviews during animation can be problematic since the web content is also resized.

UIImageView on iphone 4 image is half way out of view

I am creating an app with a simple UIImageview and scroll view for zooming.
Everything is perfect on my iPhone5/s. However, when I test the app on the iPhone 4S it does not work correctly. When I use a modal to pop the image full screen, the image is half way off the screen.
Again, this ONLY happens on the 4S and not the 5.
I tried changing the anchor points, forcing sizing but nothing works
Also, after I change my orientation from portrait to land scape and back, it goes back into "position"
I am also using constraints as my scrollview is horizontal and vertical center in my main view and the image view is horizontal vertical center in the scroll view.
Thank you in advance.
some relevant code:
image = [UIImage imageNamed:self.myImage];
[self.scrollView setTranslatesAutoresizingMaskIntoConstraints:YES];
[self.imageView setTranslatesAutoresizingMaskIntoConstraints:YES];
[self.myView setTranslatesAutoresizingMaskIntoConstraints:YES];
[im setBackgroundColor:[UIColor blackColor]];
im.contentMode = UIViewContentModeScaleAspectFit;
[self.scrollView setZoomScale:self.scrollView.minimumZoomScale
animated:YES];
NSLog(#"%F",img.size.height);
CGFloat imgheight = image.size.height;
CGFloat imgwidth = image.size. width;
CGSize imageSize = [self currentScreenBoundsDependOnOrientation];
self.scrollView.frame = CGRectMake(0,
0,
imageSize.width,
imageSize.height);
self.imageView.frame = CGRectMake(0,
0,
imageSize.width,
imageSize.height);
dan = true;
self.scrollView.delegate = self;
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(handleDoubleTap:)];
[doubleTap setNumberOfTapsRequired:2];
[self.scrollView addGestureRecognizer:doubleTap];
self.scrollView.minimumZoomScale = 1;
self.scrollView.maximumZoomScale = 2.4;
self.scrollView.scrollEnabled = YES;
self.scrollView.zoomScale = self.scrollView.minimumZoomScale;

UIScrollview doesn't scroll iOS

I'm creating several scroll views in one view that scroll horizontally. The following code works fine:
-(void)updateSection {
builder = [NSMutableArray array];
float xPosition = 0;
float xposbut = 100;
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 100, self.frame.size.width, self.frame.size.height - 69)];
scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
scrollView.delegate = self;
[self addSubview:scrollView];
for (int i = 1; i < itemArticleArray.count; i++) {
ItemView *item = [ItemView loadNibs];
item.frame = CGRectMake(xposbut, 10, item.frame.size.width, item.frame.size.height);
xPosition += scrollView.frame.size.width + 2;
xposbut += 500;
UIView *seperatorView = [[UIView alloc] initWithFrame:CGRectMake(xposbut - 50, 4, 2, scrollView.frame.size.height - 8)];
[scrollView addSubview:seperatorView];
xPosition += scrollView.frame.size.width + 4;
[scrollView addSubview: item];
[builder addObject:item];
}
[scrollView setContentSize:CGSizeMake(xposbut, scrollView.frame.size.height)];
[self addSubview:scrollView];
}
However, when I change the 8th line of code to the following:
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 400, self.frame.size.width, self.frame.size.height - 69)];
It cause the layout to look fine, but the scroll views do then not scroll at all. Any ideas?
you set the contentSize.height to the scrollView.frame.size.height and so the scrollView cant scroll. you have to set the contentSize to the total height of you scrollView, including the not visible area. The frame is only the area on screen.
UIScrollview will scroll when content size is bigger then frame size. In your code you set content size equal to frame size that's why your scrollview is not scrolling.
Set the content size for the scroll view. The content size should be greater than frame.size, then only the scroll view will scroll. And also enable scrolling.
Use the code
scrollView.scrollEnabled=YES;
scrollView.contentSize=CGSizeMake(CGFloat width, CGFloat height);
Height should be greater than scrollView.frame.size.height and add contents inside scrollview beyond the scrolview's frame.
You must give the scroll some space to work so check this out:
Create the scroll in the storyboard
Create an outlet for the scroll
And the in the .m file you must paste these lines
The code:
(void)viewDidLoad {
[super viewDidLoad];
yourScroll.scrollEnabled=YES;
yourScroll.contentSize=CGSizeMake(self.view.frame.size.width, self.view.frame.size.height*2);
}
/*
* yourScroll.contentSize=CGSizeMake(your desired scroll width, your desired scroll height);
* The values must be bigger than the viewController size
*/

How do I use UIPageControl in my app?

I am making an app where I need some images can be scrolled through using a UIPageControl. Sadly, I don't know how to use a UIPageControl, or a UIScrollView either. A link to a YouTube video or Xcode documentation by Apple would be much appreciated!
Thanks in advance!!
here is a code which will help you
CGSize size = [[UIScreen mainScreen] bounds].size;
CGFloat frameX = size.width;
CGFloat frameY = size.height-30; //padding for UIpageControl
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(offsetX, offsetY, frameX, frameY)];
scrollView.pagingEnabled = YES;
scrollView.backgroundColor = [UIColor clearColor];
scrollView.contentSize = CGSizeMake(frameX, frameY);
[self.view addSubview: scrollView];
// let say you have array of image in imageArray
for(int i = 0; i < [imageArray]; i++)
{
UIImage *image = [UIImage imageNamed:[imageArray objectAtIndex:i]];
imageView = [[UIImageView alloc] initWithImage:image];
imageView.frame = CGRectMake(frameX * i, 0.0, frameX, frameY);
[scrollView addSubview:imageView];
}
scrollView.contentSize = CGSizeMake(frameX*[imageArray count], frameY);
please declare the variables according to scope of use. i have declared all the variables locally so that might not get confuse and also add the UIPageControl at the bottom of your viewcontroller
Implement the delegate method of UIScrollView to the current Page indicator
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
float width = scrollView.frame.size.width;
float xPos = scrollView.contentOffset.x+10;
//Calculate the page we are on based on x coordinate position and width of scroll view
pageControl.currentPage = (int)xPos/width;
}
where pageControl is UIPageControl added on bottom your viewcontroller
ScrollView:
ScrollView is used to display the more number views/Objects. We can display those views by horizontal or vertical scrolling.
You can handle zooming, panning, scrolling etc.
You can go through some of these tutorials
Are there any good UIScrollView Tutorials on the net?
https://developer.apple.com/library/ios/documentation/windowsviews/conceptual/UIScrollView_pg/CreatingBasicScrollViews/CreatingBasicScrollViews.html
Example Code for Scrollview:
UIScrollView *scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0,self.view.frame.size.width, self.view.frame.size.height)];
//This will create a scrollview of device screen frame
You can enable the scrolling by
scroll.scrollEnabled = YES;
Example for adding 3 views to scrollview
NSInteger numberOfViews = 3;
for (int i = 0; i < numberOfViews; i++) {
CGFloat xOrigin = i * self.view.frame.size.width;
UIView *awesomeView = [[UIView alloc] initWithFrame:CGRectMake(xOrigin, 0, self.view.frame.size.width, self.view.frame.size.height)];
awesomeView.backgroundColor = [UIColor colorWithRed:0.5/i green:0.5 blue:0.5 alpha:1];
[scroll addSubview:awesomeView];
[awesomeView release];
}
// 3 views added horizontally to the scrollview by using xOrigin.
The most important part in this for is to understand the xOrigin. This will place every UIView exactly where the previous UIView has stopped, in other words, each UIView will start at the end of the previous one.
Now we got the scrollview with 3 views added horrizontally.
Set the UIScrollView contentSize
scroll.contentSize = CGSizeMake(self.view.frame.size.width * numberOfViews, self.view.frame.size.height);
The contentSize is just the sum of the widths of the three UIViews, if the width of each UIView is 320, and we have three UIViews, your contentSize width will be 920.
[self.view addSubview:scroll];
[scroll release];
//Add scrollview to viewcontroller
Page Control:
A Page control presents the user with a set of horizontal dots representing pages. The current page is presented as a white dot. The user can go from the current page to the next or to the previous page.
To enable paging you need to add
scroll.pagingEnabled = YES;
pageControl = [[UIPageControl alloc] init]; //SET a property of UIPageControl
pageControl.frame = CGRectMake(100,self.view.frame.size.height-100,self.view.frame.size.width-200,100);
pageControl.numberOfPages = 3; //as we added 3 diff views
pageControl.currentPage = 0;
Add delegate method of scrollview to implement the pagecontrol dots while scrolling
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat pageWidth = self.scrollView.frame.size.width;
int page = floor((self.scrollView.contentOffset.x – pageWidth / 2 ) / pageWidth) + 1; //this provide you the page number
pageControl.currentPage = page;// this displays the white dot as current page
}
Now you can see pagecontrol for scrollview. Hope you understand. Refer this too
https://developer.apple.com/library/ios/documentation/uikit/reference/UIPageControl_Class/Reference/Reference.html
This is a very good tutorial by the Ray Wenderlich team on how to set up a paging scrollview: How To Use UIScrollView to Scroll and Zoom Content
Apple's documentation also has an example of how to implement a paging scroll view: PhotoScroller
My answer to this previous question may also be useful to you.

Resources