0

I have an UIScrollView and horizontally scrollable content. I can properly set up the content size, etc, but I need to place another similar ScrollView just below the first one. So, I need to make height of the ScrollView to be equal to height of its content. Currently I use this code, but it does not work. I attached screenshot with issue and the code:

//setting the correct content size of scrollView (self.contentSize is already calculated)
self.imageScrollView.contentSize = self.contentSize;
//creating temporary CGRect
CGRect frame = self.imageScrollView.frame;
//Changing the height and re-assigning new frame to imageScrollView
frame.size.height = self.contentSize.height;
self.imageScrollView.frame = frame;

Look at the screenshot: the imageScrollView is just below NavBar. The content still scrollable and the size of ScrollView is smaller than content size. ScrollView frame cannot be set

Idris
  • 997
  • 2
  • 10
  • 27
Richard Topchii
  • 7,075
  • 8
  • 48
  • 115
  • What about the scrollView itself, are you sure scrollView.frame.origin.y set correctly? – modusCell Jul 26 '14 at 17:51
  • I've set it in storyboard as usual, the top left corner at 0,0 position, so AT NavBar, but in all other cases it were OK. – Richard Topchii Jul 26 '14 at 17:55
  • It looks like imageScrollView is in fact the proper height, but is just hidden underneath the nav bar. What happens if you move it down by the height of the nav bar? Can you see the whole scroll view then? – Lyndsey Scott Jul 26 '14 at 17:56
  • Even if I make it so: `frame.origin.y = 300.0f;`, it does not help. It does nothing and doesn't change the position of the ScrollView – Richard Topchii Jul 26 '14 at 18:01
  • That's because you can't set the frame that way. You need to set it like so: frame = CGRectMake(x,y,width,height); – Lyndsey Scott Jul 26 '14 at 18:02
  • @RichardTopchiy if you give 0 to scrollView y it goes under the navigation bar. – modusCell Jul 26 '14 at 23:30

1 Answers1

2

You can't set the frame's height using frame.size.height = self.contentSize.height;

Instead use frame = CGRectMake(x, y, width, height); Ex:

self.imageScrollView.frame = CGRectMake(self.imageScrollView.frame.origin.x, self.imageScrollView.frame.origin.y, self.imageScrollView.frame.size.width, self.contentSize.height);

And from the looks of things, I suspect the content size of your imageScrollView is correct, but it's being hidden by your nav bar. In which case, I recommend setting imageScrollView frame's origin to the height of the nav bar, ex:

self.imageScrollView.frame = CGRectMake(self.imageScrollView.frame.origin.x, self.navigationController.navigationBar.frame.size.height, self.imageScrollView.frame.size.width, self.contentSize.height);

Update #1: Here's a link to a great answer explaining why you can't set the frame in the way you've attempted: ios frame change one property (eg width)

So basically you can edit a lone CGRect structure by changing a single property, but you can NOT update a CGRect in that way if it's a property of another object -- in this case a property of a frame.

Update #2: Also, to change the position of elements in your interface, place the code in viewDidLayoutSubviews, not in viewDidLoad.

Update #3: To have the code in viewDidLayoutSubviews only processed once, enclose it in a conditional, ex:

bool subviewsLaidout;

- (void)viewDidLoad {
    subviewsLaidout = NO;
}

- (void)viewDidLayoutSubviews {
    if (!subviewsLaidout) {
        self.imageScrollView.frame = CGRectMake(self.imageScrollView.frame.origin.x, self.navigationController.navigationBar.frame.size.height, self.imageScrollView.frame.size.width, self.contentSize.height);
        subviewsLaidout = YES;
    }
}
Community
  • 1
  • 1
Lyndsey Scott
  • 37,080
  • 10
  • 92
  • 128
  • 1
    Used this code: `self.imageScrollView.frame = CGRectMake(self.imageScrollView.frame.origin.x, self.navigationController.navigationBar.frame.size.height, self.imageScrollView.frame.size.width, self.contentSize.height);`, does not change anything. Can't see any point in doing so, because I firstly take the frame to variable, then, change the variable and only then assigning the var to the frame, as in your example. I made it only to make it easier. – Richard Topchii Jul 26 '14 at 18:09
  • Could you explain, why? As I remember, I already done this kind of code and it worked – Richard Topchii Jul 26 '14 at 18:12
  • @RichardTopchiy I just posted a link to a post with a really good explanation – Lyndsey Scott Jul 26 '14 at 18:19
  • Thanx a lot! I think I also checked AutoLayout solution, seems, it does not work – Richard Topchii Jul 26 '14 at 18:20
  • Are you putting this code in viewDidLoad? If so, put it in viewDidLayoutSubviews instead. – Lyndsey Scott Jul 26 '14 at 18:23
  • I can't do this, cause it is being called quite frequently and it can slow down the performance, I think, its bad idea. – Richard Topchii Jul 26 '14 at 18:34
  • You can add a variable to viewDidLayoutSubviews, ex. subviewsLaidout = YES, so it's only called once. I'll add this to my answer. – Lyndsey Scott Jul 26 '14 at 18:38