UIScrollView contentSize Issue - With example code - iphone

Within my view I create a scrollview with a width of 320 and a height of 70.
Responding to the user touching a button, I expand the scrollview, so it is 380(h) x 320(w) in size.
The code for this is shown below:
CGRect scrollviewFrame = CGRectMake(0, 30, 320, 380);
[scrollView setFrame:scrollviewFrame];
[self layoutScrollImages:YES];
CGSize srect = CGSizeMake([scrollView bounds].size.width, (kNumImages * (kScrollObjHeight + 10)));
[scrollView setContentSize:srect];
The constants mentioned in the above snippet are defined as:
const CGFloat kScrollObjHeight = 80;
const NSUInteger kNumImages = 100;
As I debug this project, I can see that srect is 320 (w) x 8000 (h) in size; however my issue is the scrollable area (where the user can actually touch to scroll the scrollview) remains the same as when it was it's original size.
I'm obviously missing something, does anyone know what it is?
have created a sample project to illustrate the issue I am having, it is available here: http://dl.dropbox.com/u/9930498/ScrollViewTest.zip

The problem in your sample is you have a very odd structure for loading your views. As such the view you're adding to the DetailScrollView instance is the root view of the DetailScrollView.xib, not the scrollview itself, which I believe is what you were expecting.
Fastest way to fix your problem is to adjust the root view in DetailScrollView.xib to autoresize width and height.

A UIView cannot respond to touches that are outside of the bounds of its superview. In your example, it appears that you expand the scroll view, but the scroll view's parent is still only 100 units high.

You should imagine the scrollView as a window, where by the window I mean the frame of the scrollView, which is also the coordinates that the scrollView detects your touches. By setting the contentView as 320 (w) x 8000 (h) you only change the content of the scroll view, which is the complete area behind that window.
By expanding content view, the scrollView can scroll a broader area, but in order to detect touches in a bigger rect, you should change frame of the scroll view.

Related

UIScrollView contentOffset resets when tapped

I have a UIScrollView which resets its contentOffset anytime the view is tapped.
This is demonstrated here: https://gyazo.com/c8fb5c0fa5b6d53acf45c809dcb5b251
What I've tried:
Disabling keyboard dismissal
Checking for isDragging on scrollViewDidScroll and resetting the content offset if it was false. This resulted in jumpy behavior.
Reading this question, it did not help.
You can test it yourself here: https://github.com/willbishop/scrollviewwizardry
Any ideas?
You could turn off paging if that is not the intended result you're looking for:
scrollView.isPagingEnabled = false
If paging is something you're looking to use:
Paging is meant for snapping between multiple views in a ScrollView, usually where each subview is the size of the ScrollView's bounds. Since you've enabled paging with vertical scrolling, and your ScrollView content height is less than two "pages" height, unexpected results from paging are occurring.
For your situation, if you set each view in your ScrollView equal to the ScrollView's height, and your ScrollView contentSize height is equal to its subview's combined height, then paging works properly and the content offset doesn't reset when tapped:
scrollView.frame.size.height = view.frame.height
subView1.frame.size.height = view.frame.height
subView2.frame.size.height = view.frame.height
scrollView.contentSize.height = subView1.frame.height + subView2.frame.height
It will snap between showing your two views when the ScrollView stops being scrolled. You could also have your "peekAmount" where the second view shows at the bottom while still scrolled to the top "page", as long as the height of your ScrollView contentSize is equal to twice the ScrollView bounds height (i.e. two pages).

Scroll View Content Width Change During Rotation (Autolayout) - Scroll View wrong size

I have a scroll view that has a content view inside of it.
The scroll view has constraints to the top, bottom, leading and trailing content view and top, leading, trialing superview with the bottom space to the bottom layout.
I change the Content View width on rotation:
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
{
_contentWidth.constant = 480;
}else{
//iPhone Portrait
_contentWidth.constant = 320;
}
}
When I run the app and rotate to landscape, the width of the Content View changes and everything looks good, but the scroll view only allows scrolling on the left half of the screen (the whole view scrolls but your finger must be on the left side of screen to scroll). The Scroll View frame = (0 0; 320 431);.
If I go to another tab on my tab bar and return to this View the frame = (0 0; 480 320); what it is supposed to be and everything works/looks fine.
Any ideas what I need to do to get this by not selecting another tab and coming back?
EDIT
I made a subclass of Content View called ContentViewSubclass and put the following method in it:
-(CGSize)intrinsicContentSize{
CGSize size;
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
{
size.height = 1000;
size.width = 480;
return size;
}else{
//iPhone Portrait
size.height = 1000;
size.width = 320;
return size;
}
}
Then on my ViewController.m I updated to the following code:
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
[_contentView invalidateIntrinsicContentSize];
[_contentView intrinsicContentSize];
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
{ _contentWidth.constant = 480;
_contentHeight.constant = 1000;
}else{
//iPhone Portrait
_contentWidth.constant = 320;
_contentHeight.constant = 1000;
}
}
When I log the sizes I get
Landscape:
ContentViewSubclass frame is (0 0, 480 1000)
UIScrollView frame is (0 20, 480 251)
contentView intrinsic size is {480, 1000}
Portrait:
ContentViewSubclass frame is (0 0; 320 1000)
UIScrollView frame is (0 20, 320 411)
contentView intrinsic size is {320, 1000}
Everything is in a Tab Bar View Controller and here is what it is set up like:
View
ScrollView
ContentView
Labels (many)
Textfields (many)
TableView (2)
CollectionViewSubcless (1)
I deleted the table views and Collection View in case they were causing problems and that didn't help.
Same issue. I get the correct layout on everything and it all scrolls, but you have be touching the left half of screen in landscape to scroll it. If I go to another tab view and return to this one it works correct. The scroll view then shows UIScrollView frame is (0 20, 480 300).
You're using the "Pure AutoLayout Approach" described here by Apple in a Technical Note: https://developer.apple.com/library/ios/technotes/tn2154/_index.html
The "Pure AutoLayout Approach" works in Apple's sample code because an image view has an intrinsic content size; your content view, on the other hand, does not.
If you don't want to switch to the "Mixed Approach", then your content view will have to have an intrinsic content size. You do that by creating a UIView subclass and overriding the intrinsicContentSize method. In the willRotateToInterface… method, send invalidateIntrinsicContentSize to your content view.
I struggled with a similar situation. In my case it was the rightmost section of the landscape screen-width which is "added" to the portrait screen-width when rotated to landscape (i.e. for all values of x where: w-h < x <= w). Buttons and such which were constrained to move into that area were there, but were unresponsive. If that sounds the same as what you're seeing, then this simple solution might help. It fixed it for me.

UIScrollView setting page size dynamically

I've done quite a bit of looking into this but have been unsuccessful in finding a solution.
I have a UIScrollView called scrollView inside of UIView. I'm using this scrollView in pagingEnabled mode. Inside of scrollView, I have 3 different views created programmatically. Inside of these 3 different views, I have a bunch of stuff(UILabel,UITextView etc.). All of the views contents are dynamic and determined at runtime.So, i really don't know scrollView.contentSize. If i give the content size of this scrollView,Sometimes ,I have a screen with white blank at the botton of the screen when user scrolls down. My question is : Can i set the content size dynamically for each single page of this scrollView? For example,for page 1 :
self.scrollViewNews.contentSize = CGSizeMake(constant1,constant2);
And set something else for page 2 as well .
I think you're confused about contentSize vs the paging size. The paging size is always the size of the scrollView bounds, and isn't a property you can otherwise set. That is, when you swipe left/right it will "page" by the width of the scrollview.
contentSize is the size of the virtual bounding box of all the subviews within the scrollview. This only serves to limit how far the scrollview will scroll, and for paging, how many times it will page, i.e. contentSize.width / bounds.size.width.
Assuming the scrollView isn't zoomed in/out (zoomScale = 1.0) then you need to position and size your subviews on the virtual 'page boundaries'. They can take up the full page boundary (be sized to match scrollview.bounds) or be inset. If you have some content that is larger/smaller then you'll have to decide if you want to change the scale of that content or size it up/down within the page bounds.
Yes you can dynamically set the content size of the scrollView. Also You can use this method:
self.scrollViewNews.contentSize = CGSizeMake(constant1,constant2);
Nothing wrong this method. You are seeing the blank space at bottom because you ares setting the height of the scrollView's contentSize to a larger value than it's content. That's the issue. Adjust the height according to the contents, blank space will go.
please, try to get the actual content size from the current content.
the content must be some inherited class from the UIView and it has a frame.size.width and frame.size.height property.
you can use those to set the contentSize of your UIScrollview for the current content at that time when you add the content to the UIScrollView.
Yeah. You can set the scrollView size dynamically through
scroller.contentSize = CGSizeMake(1650, 2000);
You can use the following property to set the dynamic frame for each pages
[urScrollView scrollRectToVisible:frame animated:YES];
if you are using pagingEnabled = YES for your scrollview
The below UIScrollViewDelegate delegate will adjust the page and content
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
int page = urScrollView.contentOffset.x/urScrollView.frame.size.width;
pageControl.currentPage = page;
}
//pager action
- (IBAction)changePage:(id)sender{
int page = pageControl.currentPage;
CGRect frame = urScrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
[urScrollView scrollRectToVisible:frame animated:YES];
}
please look at this sample app
Try out this.
- (void)viewDidLoad
{
float sizeOfContent = 0;
UIView *lLast = [scrollView.subviews lastObject];
NSInteger wd = lLast.frame.origin.y;
NSInteger ht = lLast.frame.size.height;
sizeOfContent = wd+ht;
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width, sizeOfContent);
}

iPhone CGRect - Get Frame Size?

I'm looking to find out the "lower limit" of a frame. The frame in question is a UITextView that resizes based on the size of the content e.g.
CGRect frame = mainTextBox.frame;
frame.size.height = mainTextBox.contentSize.height;
mainTextBox.frame = frame;
This works fine but it is the last item on a scrollView. So what I want to do is program the scroll view to only be as long as nessisary e.g.
[scrollView setContentSize:CGSizeMake(320,1850)]
What I want to do is make the 1850 the right size so that the scrollView finishes just below the mainTextBox.
Is there anyway to get a return as to the distance of the bottom of the frame to the top of the view?
Just add the y coordinate of the origin point (upper left corner of the view) to the height.
CGFloat lowerBound = mainTextBox.frame.origin.y + mainTextBox.frame.size.height;
would CGRectGetMaxY(mainTextBox.frame); work for your needs?

Image scroller problem

hello every buddy
i want to make horizontal image scroller at bottom view and in the back of side big Image View. i don't know how to make image horizontal scroll.
Place the image view inside a scroll view whose horizontal content size is greater than its frame width, i.e.
UIScrollView *scrollView = [[UIScrollView alloc] init];
scrollView.frame = CGRectMake(0, 0, 100, 100);
scrollView.contentSize = CGSizeMake(300, 100);
[scrollView addSubview:imageView];
You should use contentSize property of the UIScrollView to set its content size according to your requirement and then set the property showsHorizontalScrollIndicator to YES and showsVerticalScrollIndicator to NO . But you don't require to set these two if you set frame and content size properly. Like if _myScrollView.frame.height and _myScrollView.contentSize.height is same then you don't need to set horizontal and vertical scroll. Its vertical scroll will automatically be disabled.
you can use scroll view with page control for a horizontal slideshow. follow the tutorial it might help you
http://www.edumobile.org/iphone/iphone-programming-tutorials/pagecontrol-example-in-iphone/