Introduction
This technote provides some information regarding Auto Layout support for UIScrollView. Specifically it demonstrates a "mixed" and a "pure" auto layout approach for UIScrollViews.
Back to Top
In Depth Explanation
In general, Auto Layout considers the top, left, bottom, and right edges of a view to be the visible edges. That is, if you pin a view to the left edge of its superview, you’re really pinning it to the minimum x-value of the superview’s bounds. Changing the bounds origin of the superview does not change the position of the view.
The UIScrollView class scrolls its content by changing the origin of its bounds. To make this work with Auto Layout, the top, left, bottom, and right edges within a scroll view now mean the edges of its content view.
The constraints on the subviews of the scroll view must result in a size to fill, which is then interpreted as the content size of the scroll view. (This should not be confused with the intrinsicContentSize method used for Auto Layout.) To size the scroll view’s frame with Auto Layout, constraints must either be explicit regarding the width and height of the scroll view, or the edges of the scroll view must be tied to views outside of its subtree.
Note that you can make a subview of the scroll view appear to float (not scroll) over the other scrolling content by creating constraints between the view and a view outside the scroll view’s subtree, such as the scroll view’s superview.
Here are two examples of how to configure the scroll view, first the mixed approach, and then the pure approach.
Back to Top
Mixed Approach
Position and size your scroll view with constraints external to the scroll view—that is, the translatesAutoresizingMaskIntoConstraints property is set to NO.
Create a plain UIView content view for your scroll view that will be the size you want your content to have. Make it a subview of the scroll view but let it continue to translate the autoresizing mask into constraints:
Listing 1 Mixed Approach Code Listing
- (void)viewDidLoad {
UIView *contentView;
contentView = [[UIView alloc] initWithFrame:CGRectMake(0,0,contentWidth,contentHeight)];
[scrollView addSubview:contentView];
// DON'T change contentView's translatesAutoresizingMaskIntoConstraints,
// which defaults to YES;
// Set the content size of the scroll view to match the size of the content view:
[scrollView setContentSize:CGSizeMake(contentWidth,contentHeight)];
/* the rest of your code here... */
}
Create the views you want to put inside the content view and configure their constraints so as to position them within the content view.
Alternatively, you can create a view subtree to go in the scroll view, set up your constraints, and call the systemLayoutSizeFittingSize: method (with the UILayoutFittingCompressedSize option) to find the size you want to use for your content view and the contentSize property of the scroll view.
Back to Top
Pure Auto Layout Approach
To use the pure autolayout approach do the following:
Set translatesAutoresizingMaskIntoConstraints to NO on all views involved.
Position and size your scroll view with constraints external to the scroll view.
Use constraints to lay out the subviews within the scroll view, being sure that the constraints tie to all four edges of the scroll view and do not rely on the scroll view to get their size.
A simple example would be a large image view, which has an intrinsic content size derived from the size of the image. In the viewDidLoad method of your view controller, you would include code similar to the code shown in the listing below:
Listing 2 Pure Auto Layout Approach Code Listing
- (void)viewDidLoad {
UIScrollView *scrollView;
UIImageView *imageView;
NSDictionary *viewsDictionary;
// Create the scroll view and the image view.
scrollView = [[UIScrollView alloc] init];
imageView = [[UIImageView alloc] init];
// Add an image to the image view.
[imageView setImage:[UIImage imageNamed:"MyReallyBigImage"]];
// Add the scroll view to our view.
[self.view addSubview:scrollView];
// Add the image view to the scroll view.
[scrollView addSubview:imageView];
// Set the translatesAutoresizingMaskIntoConstraints to NO so that the views autoresizing mask is not translated into auto layout constraints.
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
imageView.translatesAutoresizingMaskIntoConstraints = NO;
// Set the constraints for the scroll view and the image view.
viewsDictionary = NSDictionaryOfVariableBindings(scrollView, imageView);
[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:|[imageView]|" options:0 metrics: 0 views:viewsDictionary]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[imageView]|" options:0 metrics: 0 views:viewsDictionary]];
/* the rest of your code here... */
}
This would give you a scroll view that resized as the view controller’s view resized (such as on device rotation), and the image view would be a scrolling subview. You don’t have to set the content size of the scroll view.
Back to Top
Document Revision History
Date Notes
2014-02-20
Fixed some typographical errors.
2013-05-08
New document that describes how to work with UIScrollView and autolayout.
最后写一个简单的demo给大家
- (void)viewDidLoad {
[super viewDidLoad];
//方案一:使用一个容器
UIScrollView *scrollView = [[UIScrollView alloc]init];
scrollView.backgroundColor = [UIColor orangeColor];
scrollView.pagingEnabled =YES;
[self.view addSubview:scrollView];
[scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.and.left.mas_equalTo(60);
make.right.mas_equalTo(-60);
make.height.mas_equalTo(100);
}];
UIView *containerView = [[UIView alloc]init];
containerView.backgroundColor = [UIColor redColor];
[scrollView addSubview:containerView];
UIView *view1 = [[UIView alloc] init];
view1.backgroundColor = [UIColor yellowColor];
[containerView addSubview:view1];
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.and.bottom.equalTo(containerView);
make.width.equalTo(scrollView);
}];
UIView *view2 = [[UIView alloc] init];
view2.backgroundColor = [UIColor greenColor];
[containerView addSubview:view2];
[view2 mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.and.bottom.equalTo(containerView);
make.width.equalTo(scrollView);
make.left.equalTo(view1.mas_right);
}];
[containerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(scrollView);
make.right.mas_equalTo(view2.mas_right);
make.height.equalTo(scrollView);
}];
//方案二:不适用中间容器,也可以参考苹果官方文档里加了一个imageview,因为imageView和label都是有intrinsic size.
UIScrollView *scrollView11 = [[UIScrollView alloc]init];
scrollView11.backgroundColor = [UIColor redColor];
scrollView11.pagingEnabled =YES;
[self.view addSubview:scrollView11];
[scrollView11 mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(170);
make.left.mas_equalTo(60);
make.right.mas_equalTo(-60);
make.height.mas_equalTo(100);
}];
UIView *view11 = [[UIView alloc] init];
view11.backgroundColor = [UIColor yellowColor];
[scrollView11 addSubview:view11];
[view11 mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.and.bottom.equalTo(scrollView11);
make.width.equalTo(scrollView11);
make.height.equalTo(scrollView11);
}];
UIView *view22 = [[UIView alloc] init];
view22.backgroundColor = [UIColor greenColor];
[scrollView11 addSubview:view22];
[view22 mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.bottom.right.equalTo(scrollView11);
make.width.equalTo(scrollView11);
make.height.equalTo(scrollView11);
make.left.equalTo(view11.mas_right);
}];
}
Working with Self-Sizing Table View Cells
tableView.estimatedRowHeight = 85.0
tableView.rowHeight = UITableViewAutomaticDimension
NOTE
When working with table view cells, you cannot change the layout of the predefined content (for example, the textLabel, detailTextLabel,and imageView
properties).
The following constraints are supported:
Constraints that position your subview relative to the cell’s content view.
Constraints that position your subview relative to the cell’s bounds.
Constraints that position your subview relative to the predefined content.