示例详解:UIScrollview与Autolayout的那点事
2015-12-28 15:55:05 | 来源:玩转帮会 | 投稿:佚名 | 编辑:小柯

原标题:示例详解:UIScrollview与Autolayout的那点事

前言

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

UIView*container=[UIViewnew];
[scrollViewaddSubview:container];
[containermas_makeConstraints:^(MASConstraintMaker*make){
make.edges.equalTo(scrollView);
make.width.equalTo(scrollView);
}];
  • 为什么要用一个container包含其他subview?

  • 为什么指定了edges 还要指定width? 不是多此一举吗?

那么今天我就按照我的理解来说明一下这个问题

梳理

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

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

换成代码 是这个样子

[scrollViewmas_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

[v1mas_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);

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

[scrollViewmas_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的大小 会怎么样呢?

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

效果

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

示例3

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

[v1mas_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);
}];
[v2mas_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上面 会怎么样呢?

CGSizesize=CGSizeMake(200,200);
[v1mas_makeConstraints:^(MASConstraintMaker*make){
make.centerY.equalTo(scrollView.mas_top);
make.size.mas_equalTo(size);
}];
[v2mas_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);
}];
[v3mas_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);
}];
[v4mas_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其实是这个问题上的最佳实践

tags:

上一篇  下一篇

相关:

如何快速面试APP产品经理的问题

  HR如何快速面试APP产品经理的面试问题:  01、是否准备做背调?如果不准备的话,简历啥的就别看了,经

100个iOS开发/设计程序员面试题汇总,你将如何作答?

  无论是对于公司还是开发者或设计师个人而言,面试都是一项耗时耗钱的项目,本文作者Cameron Banga从编程

评论丨昔日北大才子 今日“铁窗”嫌犯 为何

原创 2015-12-24

付费3520附近会有支撑

上周末其实就一直在提示风险更多些了,并明确说如果周初一旦再向下时,3588将会击穿,今天的市场也基本按

做包子原来这幺简单!比买的好吃多啦!

包子是很多人的日常早餐很多人问菜菜包子怎幺做今天就教大家在家做包子北方能手们有什幺更好的方法食材:麦

【战舰收评】借B股大跌洗盘,关注20均争夺

盘面上看:周一早盘沪深两市双双高开,券商、二胎等板块盘初在政策消息刺激下表现活跃,带动指数冲高,然而

由Jacques传回的现场特效实料

可能很多人理解中的特效属于“影视后期”的组成部分,那为什幺我们的特效总监Jacques会全程跟组?
其实,在

【奇葩历史】第一次电影在地下室放映,而且很恐怖

1895年12月28日,在法国巴黎卡布辛路的大咖啡馆,一大群人疯狂的尖叫着,还有几个竟然冲出咖啡馆落荒而逃。

真正的古书是什幺样的?

版 式⑴ 版框 也叫边栏,指一张印页四边的围线,以围线的条数分,有四周单边、左右双边、四周双边等。⑵

李宇春926成都WhyMe演唱会:十年,我就在这里,哪都不去----正文篇5-6趴

李宇春926成都WhyMe演唱会:十年,我就在这里,哪都不去----正文篇5-6趴最终免责导读9

站长推荐: