UIScrollview 与 Autolayout 的那点事

来源:里脊串的开发随笔git

 

前言github

 

自从写了介绍Masonry那篇文章之后 就一直有人对UIScrollView的那个例子不是很理解app

 

UIView *container = [UIView  new ];
[scrollView addSubview:container];
[container mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(scrollView);
make.width.equalTo(scrollView);
}];

 

  • 为何要用一个container包含其余subview?iphone

  • 为何指定了edges 还要指定width? 不是画蛇添足吗?布局

 

那么今天我就按照个人理解来讲明一下这个问题ui

 

梳理spa

 

直入主题 要解释以前的问题 最重要的一个概念就是code

 

UIScrollView依靠与其subviews之间的约束来肯定ContentSize的大小blog

 

换成代码 是这个样子ip

 

[scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(v1.mas_left);
make.right.equalTo(v1.mas_right);
make.top.equalTo(v1.mas_top);
make.bottom.equalTo(v1.mas_bottom);
}];

 

这是由于UIScrollView是个很是特殊的view UIScrollView与其subview之间相对位置的约束 并不会直接用于frame的计算 而是会转化为对ContentSize的计算

 

换句话说 当UIScrollView知道了上下左右的约束分别指向subview什么位置以后 只要subview的位置固定下来了 ContentSize的大小就肯定下来了

 

下面来个简单的例子 强烈建议配合demo来理解下面的例子(demo的连接在文尾)

 

请点击->在线演示 (为了方便理解 我将ContentSize用红线框了出来 另外为了查看ContentSize 我把UIScrollView的clipTobounds关闭了 能够经过左上角的开关来切换实际的效果)

 

示例1

 

[v1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(scrollView);
make.width.equalTo(scrollView);
make.height.equalTo(scrollView).multipliedBy(1.5);
}];

 

效果

这里我创建了一个宽等于scrollview 高等于scrollview高度1.5倍的view 而后scrollview成功的计算出了ContentSize

 

关键就在于

 

make.edges.equalTo(scrollView);

 

这句话其实等同与以前我提到的

 

[scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(v1.mas_left);
make.right.equalTo(v1.mas_right);
make.top.equalTo(v1.mas_top);
make.bottom.equalTo(v1.mas_bottom);
}];

 

scrollview由于上面的约束 会以v1的大小来计算ContentSize

 

示例2

 

若是尝试改变v1的大小 会怎么样呢?

 

[v1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(scrollView);
 
make.size.equalTo(scrollView).sizeOffset(CGSizeMake(80, 80));
}];

 

效果

能看到 当我仅改变v1的大小 而不变其余的东西的状况下 scrollview的ContentSize也是随着v1的大小变化而变化的

 

示例3

 

接下来示例就会稍微复杂点 若是同时有两个view 会如何呢?

 

[v1 mas_makeConstraints:^(MASConstraintMaker *make) {
 
make.left.top.right.equalTo(scrollView).insets(UIEdgeInsetsMake(10, 10, 0, 10));
 
make.width.equalTo(scrollView).multipliedBy(1.1);
make.bottom.equalTo(v2.mas_top).offset(-50);
make.height.equalTo(@200);
}];
[v2 mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(scrollView);
 
make.left.right.equalTo(v1).insets(UIEdgeInsetsMake(0, 50, 0, 50));
make.height.equalTo(@250);
}];

 

效果

这个例子中 scrollview的四个方向的约束并无放在同一个subview上 而是分别指向了两个view 因此scrollview的ContentSize会根据两个view之间的约束来肯定

 

示例4

 

若是将四个方向的约束分别放到四个不一样的view上面 会怎么样呢?

 

CGSize size = CGSizeMake(200, 200);
[v1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(scrollView.mas_top);
 
make.size.mas_equalTo(size);
}];
[v2 mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(scrollView.mas_left);
 
make.size.mas_equalTo(size);
make.right.equalTo(v1.mas_left);
make.top.equalTo(v1.mas_bottom);
}];
[v3 mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(scrollView.mas_right);
 
make.size.mas_equalTo(size);
make.left.equalTo(v1.mas_right);
make.top.equalTo(v1.mas_bottom);
}];
[v4 mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(scrollView.mas_bottom);
 
make.size.mas_equalTo(size);
make.left.equalTo(v1.mas_left);
make.top.equalTo(v2.mas_bottom);
}];

 

效果

将四个方向的约束分别指向四个view的中心点 咱们也能获得正确的ContentSize

 

若是你看懂了示例4的代码与效果 相信你对这个问题的全部疑惑都应该已经解除了

 

那么再回到最开始那个问题

 

make.edges.equalTo(scrollView);
make.width.equalTo(scrollView);

 

通常状况下咱们使用UIScrollView来进行autolayout布局 都是为了实现相似Android中的线性布局(有不少杂的非重复性的subview 若是使用UITableView和UICollectionView太麻烦) 这时直接使用UIScrollView就会很灵活

 

那么

 

若是咱们须要竖向的滑动 就把width设为和scrollview相同

 

若是须要横向的滑动 就把height设为和scrollview相同

 

就是这么简单

 

小结

 

源码和Demo请点这里

 

前不久@nixzhu也写了一篇关于UIScrollView的文章 而后我在微博上回复说“使用一个单一的containerView占满所有,而后把全部的subview添加到containerView中” 不过nixzh 表示他是极力避免这样的 可是后在这个问题上 我是极力推荐这样使用的

 

就如同示例1和示例2同样 若是你须要添加subview 你只要简单的添加到v1上 并添加与v1的约束 就能够得到正确的ContentSize了

 

若是不这样作 就相似示例3和示例4 这些边界约束都须要一个一个的设置 这实际上是没有必要的

 

使用单一的containerView实际上是这个问题上的最佳实践

相关文章
相关标签/搜索