UIView height based on content with Autolayout - cocoa-touch

I'm trying to create a section header in a UITableview that contains 3 labels, with a layout that looks a bit like this
-------------------------------
| title | dist |
| |
| Description |
| |
-------------------------------
Title and time are both fixed size, but the description needs to automatically adjust its height based on the content, with a minimum height of a single line of text.
My current header structure consists of
UIView
|_ UIView
|_ UILabel
|_ UILabel
|_ UILabel
The outer UIView is the section header itself, with a clear background, and the inner UIView is the visible view with the labels.
What I'm after, is for the section header to adjust it's height according to the content that is in the description label.
I've tried implementing the tableView:heightForHeaderInSection: but it doesn't seem to be working. iOS is complaining about having to break constraints which I guess makes sense given I've set constraints, but then manually override them with this method?
How can I create constraints that allow the view to resize itself? Right now, I have the following implementation of viewForHeaderInSection:
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if (section == 0) {
UIView *header = [UIView new];
UIView *headerBg = [UIView new];
UILabel *title = [UILabel new];
UILabel *distance = [UILabel new];
UILabel *desc = [UILabel new];
headerBg.translatesAutoresizingMaskIntoConstraints = NO;
title.translatesAutoresizingMaskIntoConstraints = NO;
distance.translatesAutoresizingMaskIntoConstraints = NO;
desc.translatesAutoresizingMaskIntoConstraints = NO;
[headerBg setBackgroundColor:[UIColor colorWithWhite:1.0 alpha:0.8]];
[title setFont:[UIFont fontWithName:#"HelveticaNeue-Bold" size:14.0]];
[title setTextColor:kFONT_COLOUR];
NSString *address = _place.address ? (_place.address.length > 0 ? _place.address : #"Unknown Address") : #"Unknown Address";
[title setText:address];
[distance setFont:[UIFont fontWithName:#"HelveticaNeue" size:14.0]];
[distance setTextColor:kFONT_COLOUR];
[distance setText:#"Distance: ?m"];
[distance setTextAlignment:NSTextAlignmentRight];
[desc setFont:[UIFont fontWithName:#"HelveticaNeue" size:11.0]];
[desc setTextColor:kFONT_COLOUR];
[desc setNumberOfLines:0];
[desc setLineBreakMode:NSLineBreakByWordWrapping];
[desc setText:_place.desc ? (_place.desc.length > 0 ? _place.desc : #"No Description Given") : #"No Description Given"];
[headerBg addSubview:title];
[headerBg addSubview:distance];
[headerBg addSubview:desc];
NSDictionary *bindings = NSDictionaryOfVariableBindings(title, distance, desc, headerBg);
[headerBg addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"|-9-[title]-[distance(100)]-9-|" options:NSLayoutFormatAlignAllBaseline metrics:nil views:bindings]];
[headerBg addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"|-9-[desc]-9-|" options:NSLayoutFormatAlignAllBaseline metrics:nil views:bindings]];
[headerBg addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-9-[title(20)]-[desc]-|" options:NSLayoutFormatAlignAllLeading metrics:nil views:bindings]];
[header addSubview:headerBg];
[header addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"|[headerBg]|" options:NSLayoutFormatAlignAllBaseline metrics:nil views:bindings]];
[header addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[headerBg]-9-|" options:NSLayoutFormatAlignAllBaseline metrics:nil views:bindings]];
return header;
}
return nil;
}
Any help would be great :)

Related

UILabel too large to display Ignoring bogus layer

I want to display a whole chapter of a book with UILabel in a scrollview. But seems the content is too large to display, and gives following error:
[2835:157182] -[<_UILabelContentLayer: 0x60400023b040> display]: Ignoring bogus layer size (378.666667, 883959.333333), contentsScale 3.000000, backing store size (1136.000000, 2651878.000000)
And I searched for answers and some guys suggest I should use a CATiledLayer to solve this, but they didn't give a clear clue of how to do this, anyone could give some help?
Thanks,
- (void)viewDidLoad {
[super viewDidLoad];
/*** Init the scrollview and the label ***/
UIScrollView *scrollView= [UIScrollView new];
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:scrollView];
UILabel *scrollViewLabel = [[UILabel alloc] init];
scrollViewLabel.numberOfLines = 0;
scrollViewLabel.translatesAutoresizingMaskIntoConstraints = NO;
[scrollView addSubview:scrollViewLabel];
scrollViewLabel.text = #"";
NSArray *array = [Utils getCharptersWithName:#"mybook"];
for(NSDictionary *dic in array){
scrollViewLabel.text = [scrollViewLabel.text stringByAppendingString:[dic objectForKey:#"content"]];
}
NSLog(#"%#", scrollViewLabel.text);
/*** Auto Layout ***/
NSDictionary *views = NSDictionaryOfVariableBindings(scrollView, scrollViewLabel);
NSArray *scrollViewLabelConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[scrollViewLabel(scrollView)]" options:0 metrics:nil views:views];
[scrollView addConstraints:scrollViewLabelConstraints];
scrollViewLabelConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|[scrollViewLabel]|" options:0 metrics:nil views:views];
[scrollView addConstraints:scrollViewLabelConstraints];
NSArray *scrollViewConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|-[scrollView]-|" options:0 metrics:nil views:views];
[self.view addConstraints:scrollViewConstraints];
scrollViewConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|-[scrollView]-|" options:0 metrics:nil views:views];
[self.view addConstraints:scrollViewConstraints];
// Do any additional setup after loading the view.
}

Adding autolayout constraint programmatically turns uiview to black

I need a view controller without xib. There should be a webview with fully filled to the view. For that I've added the following code to loadView method.
- (void)loadView {
CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame];
UIView *view = [[UIView alloc] initWithFrame:applicationFrame];
view.translatesAutoresizingMaskIntoConstraints = NO;
[view setBackgroundColor:[UIColor greenColor]];
[self setView:view];
// //create webview
self.webview = [[UIWebView alloc] initWithFrame:CGRectZero];
self.webview.translatesAutoresizingMaskIntoConstraints = NO;
[view addSubview:self.webview];
[self.webview setBackgroundColor:[UIColor orangeColor]];
[self.webview setDelegate:self];
NSDictionary *viewBindings = NSDictionaryOfVariableBindings(view,_webview);
// //add constraints
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[_webview]|" options:0 metrics:nil views:viewBindings]];
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[_webview]|" options:0 metrics:nil views:viewBindings]];
}
But this turns the entire view to black. If I coment [view addConstraints:... method calls its showing a green view. What's wrong with my code?
I believe that the problem is that the parent view should not set translatesAutoresizingMaskIntoConstraints to false. The only view that must set that attribute to false is the one you are applying autolayout to, in this case webView. If you set view.translatesAutoresizingMaskIntoConstraints to false then you have to add constraints to view.
You don't need to change the root view of the UIViewController manually, maybe that's why it does not work.
My suggestion would be to try this out:
- (void) viewDidLoad {
[super viewDidLoad];
self.webview = [[UIWebView alloc] init];
self.webview.translatesAutoresizingMaskIntoConstraints = NO;
[view addSubview:self.webview];
[self.webview setBackgroundColor:[UIColor orangeColor]];
[self.webview setDelegate:self];
NSDictionary *viewBindings = NSDictionaryOfVariableBindings(view,_webview);
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[_webview]-0-|" options:0 metrics:nil views:viewBindings]];
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-0-[_webview]-0-|" options:0 metrics:nil views:viewBindings]];
// put a breakpoint after this line to see the frame of your UIWebView.
// It should be the same as the view
[self.view layoutIfNeeded];
}
This should work and your UIWebView should be full screen. Good luck!

How to use UIBezierPath in a auto layout view?

As far as I know, views displayed by constraints don't got a frame, so what should I do when I want to draw some lines in these views? Methods like moveToPoint do need a CGRect.
Here's my check: NSLog(#"%f,%f,%f,%f",self.contentView.frame.origin.x,self.contentView.frame.origin.y,self.contentView.frame.size.width,self.contentView.frame.size.height);
And the result is 0.000000,0.000000,0.000000,0.000000
For more details, here's my code:
-(void)loadView
{
self.view = [[UIView alloc]init];
self.titleView = [[UIView alloc]init];
self.placesHolder = [[UIView alloc]init];
self.contentView = [[UIView alloc]init];
self.titleView.translatesAutoresizingMaskIntoConstraints = NO;
self.placesHolder.translatesAutoresizingMaskIntoConstraints = NO;
self.contentView.translatesAutoresizingMaskIntoConstraints = NO;
self.titleView.backgroundColor = [UIColor grayColor];
self.placesHolder.backgroundColor = [UIColor blueColor];
self.contentView.backgroundColor = [UIColor redColor];
[self.view addSubview:self.titleView];
[self.view addSubview:self.placesHolder];
[self.view addSubview:self.contentView];
NSDictionary *timeLineViewMap = #{#"titleView":self.titleView,
#"placesHolder":self.placesHolder,
#"contentView":self.contentView
};
NSArray *titleHorizon = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[titleView]|" options:0 metrics:nil views:timeLineViewMap];
NSArray *placesHolderHorizon = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[placesHolder(==58)]-0-[contentView]|" options:0 metrics:nil views:timeLineViewMap];
NSArray *titleVertical = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|[titleView(==58)]-0-[placesHolder]|" options:0 metrics:nil views:timeLineViewMap];
NSArray *contentViewConstrain = [NSLayoutConstraint constraintsWithVisualFormat:#"V:[titleView]-0-[contentView]|" options:0 metrics:nil views:timeLineViewMap];
[self.view addConstraints:titleHorizon];
[self.view addConstraints:placesHolderHorizon];
[self.view addConstraints:titleVertical];
[self.view addConstraints:contentViewConstrain];
}
Of course UIView does have a frame even with AutoLayout. You just don't set the values manually, AutoLayout is doing that for you. Methods like setFrame: are still called. Simply implement drawRect: like you always did.
Well, problem kind of solved, it seems that a frame of a view don't get a size until it's on the viewDidAppear move. Then I checked some other questions like iOS AutoLayout - get frame size width, which indicate that addConstraints should be put in the viewDidLayoutSubviews method, which is not in the viewController life cycle.

NSLayoutConstraint label is in middle of image

I'm attaching a UIImageView and UILabel to a UIScrollView. I'm shrinking the image to half it's height, and when I do that, the label ends up right in the middle of the image vertically rather than right below it. If I don't force the image smaller, the label sits right below the image as expected.
How do I shrink an image and still have my label sit right below it?
UIScrollView *scrollView;
UIImageView *myImage;
NSDictionary *viewsDictionary;
UILabel *myLabel;
scrollView = [[UIScrollView alloc] init];
myImage = [[UIImageView alloc] init];
myLabel = [[UILabel alloc] init];
[myImage setImage:[UIImage imageNamed:#"vacation-house-004.jpg"]];
[myImage setContentMode: UIViewContentModeScaleAspectFill];
[myLabel setText: #"test label"];
[self.view addSubview:scrollView];
[scrollView addSubview:myImage];
[scrollView addSubview:myLabel];
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
myImage.translatesAutoresizingMaskIntoConstraints = NO;
myLabel.translatesAutoresizingMaskIntoConstraints = NO;
// Set the constraints for the scroll view and the image view.
viewsDictionary = NSDictionaryOfVariableBindings(scrollView, myImage, myLabel);
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[scrollView]|" options:0 metrics: 0 views:viewsDictionary]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[scrollView]|" options:0 metrics: 0 views:viewsDictionary]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[myImage(==scrollView)]|" options:0 metrics: 0 views:viewsDictionary]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[myImage(50)]-[myLabel]|" options:0 metrics: 0 views:viewsDictionary]];
Thank you!
Figured it out, had to add: myImage.clipsToBounds = YES;
UIView *superView = self.view;
UIScrollView *scrollView;
UIImageView *myImage;
NSDictionary *viewsDictionary;
UILabel *myLabel;
scrollView = [[UIScrollView alloc] init];
myImage = [[UIImageView alloc] init];
myLabel = [[UILabel alloc] init];
myImage.image = [UIImage imageNamed:#"vacation-house-004.jpg"];
myImage.contentMode = UIViewContentModeScaleAspectFill;
myImage.clipsToBounds = YES;
myLabel.text = #"test label";
myLabel.backgroundColor = [UIColor blackColor];
[superView addSubview:scrollView];
[scrollView addSubview:myImage];
[scrollView addSubview:myLabel];
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
myImage.translatesAutoresizingMaskIntoConstraints = NO;
myLabel.translatesAutoresizingMaskIntoConstraints = NO;
// Set the constraints for the scroll view and the image view.
viewsDictionary = NSDictionaryOfVariableBindings(superView, scrollView, myImage, myLabel);
[superView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[scrollView]|" options:0 metrics: 0 views:viewsDictionary]];
[superView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[scrollView]|" options:0 metrics: 0 views:viewsDictionary]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[myImage(==scrollView)]|" options:0 metrics: 0 views:viewsDictionary]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[myImage(150)]-[myLabel]|" options:0 metrics: 0 views:viewsDictionary]];

UIScrollView showing only part of UIView after rotation

This is my first post to Stack Overflow, and I'm a iOS beginner, so please bear with me!
I have an example app where I have three UIViews (headerView, scrollViewContainer, and bodyView) in a parent UIView (topView), and all of these views are created in code. The topView is added to a UIScrollView (pageScrollView) created in storyboard.
pageScrollView is filling the full screen of an iPhone, and I used Autolayout. The app only contains the ViewController.h and companioning .m-file seen below, plus Appdelegate.x. I think I used the single view application template to start with. I'm using iOS 6 and Xcode 4.6, but I also tried 4.5.
I've tried to remove as much as possible of other code that's irrelevant to this problem.
The problem:
When the app starts it shows all its views correctly, and the scrollView allows to view all three views as intended. But after rotating to landscape, the scrollView somehow offsets the content. For example: Stay at top and rotate = content looks OK, but scroll down a bit and rotate makes the top of the content not to show.
What I have tried: I've searched the net for help, but I haven't found anything that seemed to help me. I've added logging of various data like origin, and contentSize, and also tried to set some of them but without any success. I also used 'po [[UIWindow keyWindow] _autolayoutTrace]' to ensure that the constraints are OK.
I can't see what I'm doing wrong. Are there any obvious things missing in my code?
Thanks in advance!
Here's the ViewController.m:
#import "ViewController.h"
#interface ViewController ()
{
UIView *topView;
UIView *headerView;
UIView *bodyView;
UIView *scrollViewContainer;
UIInterfaceOrientation newOrientation;
CGFloat bodyViewHeight;
CGSize newBounds;
float pictureScrollHeight;
}
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
newBounds = [self sizeInOrientation:[UIApplication sharedApplication].statusBarOrientation];
newOrientation = [UIApplication sharedApplication].statusBarOrientation;
bodyViewHeight = 1200; // The height of the body view varies in size depending on orientation
self.pageScrollView.translatesAutoresizingMaskIntoConstraints = NO;
topView = [[UIView alloc] init];
[topView setBackgroundColor:[UIColor clearColor]];
topView.translatesAutoresizingMaskIntoConstraints = NO;
[self.pageScrollView addSubview:topView];
headerView = [[UIView alloc] init];
[headerView setBackgroundColor:[UIColor redColor]];
headerView.translatesAutoresizingMaskIntoConstraints = NO;
[topView addSubview:headerView];
scrollViewContainer = [[UIView alloc] init];
[scrollViewContainer setBackgroundColor:[UIColor blueColor]];
scrollViewContainer.translatesAutoresizingMaskIntoConstraints = NO;
[topView addSubview:scrollViewContainer];
bodyView = [[UIView alloc] init];
[bodyView setBackgroundColor:[UIColor greenColor]];
bodyView.translatesAutoresizingMaskIntoConstraints = NO;
[topView addSubview:bodyView];
[self updateViewConstraints];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)updateViewConstraints
{
[super updateViewConstraints];
// Remove old constraints
[self.view removeConstraints:self.view.constraints];
[self.pageScrollView removeConstraints:self.pageScrollView.constraints];
[topView removeConstraints:topView.constraints];
[scrollViewContainer removeConstraints:scrollViewContainer.constraints];
if ((newOrientation == UIDeviceOrientationLandscapeLeft) || (newOrientation == UIDeviceOrientationLandscapeRight)) {
pictureScrollHeight = 300;
} else {
pictureScrollHeight = 203;
}
[headerView setNeedsDisplay];
[bodyView setNeedsDisplay];
CGFloat topViewHeight = bodyViewHeight + 55 + pictureScrollHeight;
//self.pageScrollView = _pageScrollView
NSDictionary *viewsDict = NSDictionaryOfVariableBindings(_pageScrollView, topView, headerView, bodyView, scrollViewContainer);
NSDictionary *metricsDict = #{#"topViewHeight": [NSNumber numberWithFloat:topViewHeight],
#"newBoundsWidth": [NSNumber numberWithFloat:newBounds.width],
#"pictureScrollHeight": [NSNumber numberWithFloat:pictureScrollHeight],
#"bodyViewHeight": [NSNumber numberWithFloat:bodyViewHeight]};
// pageScrollView - child to self.view
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[_pageScrollView]-0-|" options:0 metrics:nil views:viewsDict]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-0-[_pageScrollView]-0-|" options:0 metrics:nil views:viewsDict]];
// topView - child to pageScrollView
[self.pageScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[topView(newBoundsWidth)]-0-|" options:0 metrics:metricsDict views:viewsDict]];
[self.pageScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-0-[topView(topViewHeight)]-0-|" options:0 metrics:metricsDict views:viewsDict]];
// headerView - child to topView
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[headerView]-0-|" options:0 metrics:nil views:viewsDict]];
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-0-[headerView(55.0)]" options:0 metrics:nil views:viewsDict]];
// scrollViewContainer - child to topView
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[scrollViewContainer]-0-|" options:0 metrics:nil views:viewsDict]];
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[headerView]-0-[scrollViewContainer(pictureScrollHeight)]" options:0 metrics:metricsDict views:viewsDict]];
// bodyView - child to topView
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[bodyView]-0-|" options:0 metrics:nil views:viewsDict]];
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[scrollViewContainer]-0-[bodyView(bodyViewHeight)]-0-|" options:0 metrics:metricsDict views:viewsDict]];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
newOrientation = toInterfaceOrientation;
newBounds = [self sizeInOrientation:toInterfaceOrientation];
}
-(CGSize) sizeInOrientation:(UIInterfaceOrientation)orientation
{
CGSize size = [UIScreen mainScreen].bounds.size;
UIApplication *application = [UIApplication sharedApplication];
if (UIInterfaceOrientationIsLandscape(orientation))
{
size = CGSizeMake(size.height, size.width);
}
if (application.statusBarHidden == NO)
{
size.height -= MIN(application.statusBarFrame.size.width, application.statusBarFrame.size.height);
}
return size;
}
#end
First of all you do not need to recreate all constraints in -updateViewConstraints method. You need to just update them in this place.
To achieve your aim do the following:
Create your constraints only once. For example in method -setupConstraints. And keep reference to those that need to be updated. See code below.
In method -updateViewConstraints just update topView height and width constraints and height for scrollViewContainer.
Here's the ViewController.m should look like:
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong) IBOutlet UIScrollView* pageScrollView;
#property (nonatomic, strong) NSLayoutConstraint* pictureHeightConstraint;
#property (nonatomic, strong) NSLayoutConstraint* topViewWidthConstraint;
#property (nonatomic, strong) NSLayoutConstraint* topViewHeightConstraint;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
newBounds = [self sizeInOrientation:[UIApplication sharedApplication].statusBarOrientation];
newOrientation = [UIApplication sharedApplication].statusBarOrientation;
bodyViewHeight = 1200; // The height of the body view varies in size depending on orientation
self.pageScrollView.translatesAutoresizingMaskIntoConstraints = NO;
topView = [[UIView alloc] init];
[topView setBackgroundColor:[UIColor clearColor]];
topView.translatesAutoresizingMaskIntoConstraints = NO;
[self.pageScrollView addSubview:topView];
headerView = [[UIView alloc] init];
[headerView setBackgroundColor:[UIColor redColor]];
headerView.translatesAutoresizingMaskIntoConstraints = NO;
[topView addSubview:headerView];
scrollViewContainer = [[UIView alloc] init];
[scrollViewContainer setBackgroundColor:[UIColor blueColor]];
scrollViewContainer.translatesAutoresizingMaskIntoConstraints = NO;
[topView addSubview:scrollViewContainer];
bodyView = [[UIView alloc] init];
[bodyView setBackgroundColor:[UIColor greenColor]];
bodyView.translatesAutoresizingMaskIntoConstraints = NO;
[topView addSubview:bodyView];
[self setupConstraints];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)setupConstraints {
// Remove old constraints
[self.view removeConstraints:self.view.constraints];
[self.pageScrollView removeConstraints:self.pageScrollView.constraints];
[topView removeConstraints:topView.constraints];
[scrollViewContainer removeConstraints:scrollViewContainer.constraints];
if ((newOrientation == UIDeviceOrientationLandscapeLeft) || (newOrientation == UIDeviceOrientationLandscapeRight)) {
pictureScrollHeight = 300;
} else {
pictureScrollHeight = 203;
}
[headerView setNeedsDisplay];
[bodyView setNeedsDisplay];
CGFloat topViewHeight = bodyViewHeight + 55 + pictureScrollHeight;
//self.pageScrollView = _pageScrollView
NSDictionary *viewsDict = NSDictionaryOfVariableBindings(_pageScrollView, topView, headerView, bodyView, scrollViewContainer);
// pageScrollView - child to self.view
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[_pageScrollView]-0-|" options:0 metrics:nil views:viewsDict]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-0- [_pageScrollView]-0-|" options:0 metrics:nil views:viewsDict]];
// topView - child to pageScrollView
[self.pageScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[topView]-0-|" options:0 metrics:nil views:viewsDict]];
[self.pageScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-0-[topView]-0-|" options:0 metrics:nil views:viewsDict]];
NSLayoutConstraint* topViewWidthConstraint = [NSLayoutConstraint constraintWithItem:topView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:newBounds.width];
self.topViewWidthConstraint = topViewWidthConstraint;
[topView addConstraint:self.topViewWidthConstraint];
NSLayoutConstraint* topViewHeightConstraint = [NSLayoutConstraint constraintWithItem:topView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:topViewHeight];
self.topViewHeightConstraint = topViewHeightConstraint;
[topView addConstraint:self.topViewHeightConstraint];
// headerView - child to topView
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[headerView]-0-|" options:0 metrics:nil views:viewsDict]];
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-0-[headerView(55.0)]" options:0 metrics:nil views:viewsDict]];
// scrollViewContainer - child to topView
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[scrollViewContainer]-0-|" options:0 metrics:nil views:viewsDict]];
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[headerView]-0-[scrollViewContainer]" options:0 metrics:nil views:viewsDict]];
NSLayoutConstraint* pictureHeightConstraint = [NSLayoutConstraint constraintWithItem:scrollViewContainer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:pictureScrollHeight];
self.pictureHeightConstraint = pictureHeightConstraint;
[scrollViewContainer addConstraint:self.pictureHeightConstraint];
// bodyView - child to topView
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[bodyView]-0-|" options:0 metrics:nil views:viewsDict]];
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V: [scrollViewContainer]-0-[bodyView]-0-|" options:0 metrics:nil views:viewsDict]];
}
- (void)updateViewConstraints
{
[super updateViewConstraints];
if ((newOrientation == UIDeviceOrientationLandscapeLeft) || (newOrientation == UIDeviceOrientationLandscapeRight)) {
pictureScrollHeight = 300;
} else {
pictureScrollHeight = 203;
}
CGFloat topViewHeight = bodyViewHeight + 55 + pictureScrollHeight;
self.pictureHeightConstraint.constant = pictureScrollHeight;
self.topViewHeightConstraint.constant = topViewHeight;
self.topViewWidthConstraint.constant = newBounds.width;
[self.pageScrollView setNeedsUpdateConstraints];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
newBounds = [self sizeInOrientation:toInterfaceOrientation];
}
-(CGSize)sizeInOrientation:(UIInterfaceOrientation)orientation
{
CGSize size = [UIScreen mainScreen].bounds.size;
UIApplication *application = [UIApplication sharedApplication];
if (UIInterfaceOrientationIsLandscape(orientation))
{
size = CGSizeMake(size.height, size.width);
}
if (application.statusBarHidden == NO)
{
size.height -= MIN(application.statusBarFrame.size.width, application.statusBarFrame.size.height);
}
return size;
}
#end
ScrollView calculates its content size automatically depending on subviews constraints added into it. Off course it works only in autolayout enviroument.
Check the auto-resizing masks.
[self.pageScrollView setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
It looks like that you are NOT doing anything with the newBounds in willRotateToInterfaceOrientation. Shouldn't you call your updateView method after getting the new bounds.