原文  http://www.cocoachina.com/ios/20151221/14757.html

前言

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

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

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

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

梳理

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

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

换成代码 是这个样子

[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其实是这个问题上的最佳实践

 

UIScrollview 与 Autolayout 的那点事的更多相关文章

  1. 示例详解:UIScrollview 与 Autolayout 的那点事

    前言 自从写了介绍Masonry那篇文章以后 就一直有人对UIScrollView的那个例子不是很理解 UIView *container = [UIView new]; [scrollView ad ...

  2. UIScrollView在AutoLayout下的滚动问题

    使用Storyboard编写UI,设置支持AutoLayout. 在其中的一个场景上,添加一个UIScrollView,在对应的代码里增加 - (void)viewDidLoad { [super v ...

  3. UIScrollView使用autolayout 垂直滚动

    转自:http://dadage456.blog.163.com/blog/static/30310744201491141752716 1.创建一个空白的UIViewController .将UIS ...

  4. UIScrollView的AutoLayout约束

    首先UIScrollview包含自身的frame和contentSize二个部分.frame决定其展示给用户的可见区域,contentSize决定其整个内容的大小.如果frame的宽高小于conten ...

  5. iOS UIScrollView使用Autolayout

    最近项目在迭代更新的时候,需要在之前用Autolayout写的界面里添加一个button,添加完这个button后,iPhone5,iPhone4显示不全了.遇到整个问题后很自然就想到了用UIScro ...

  6. iOS— UIScrollView和 UIPageControl之间的那些事

    本代码主要实现在固定的位置滑动图片可以切换. 目录图如下: ViewController.h #import <UIKit/UIKit.h> // 通过宏定义定义宽和高 #define W ...

  7. Storyboard中使用UIscrollView添加约束的开发总结

    第一次在项目中用storyboard做界面,一般的界面直接添加约束非常爽快 然后有个界面有scrollview,添加了约束还总是出错 刚开始使用了 wCompact,hRegular,滑动出现问题,有 ...

  8. 【原】Masonry+UIScrollView的使用注意事项

    [原]Masonry+UIScrollView的使用注意事项 本文转载请注明出处 —— polobymulberry-博客园 1.问题描述 我想实现的使用在一个UIScrollView依次添加三个UI ...

  9. iOS autoLayout总结

    本文转自 http://ruikq.github.io/ios/autolayout/uiscrollview/2015/01/27/iOS-autolayout%E6%80%BB%E7%BB%93. ...

随机推荐

  1. Mysql常用配置及优化

    [client]# 该目录下的内容常用来进行localhost登陆,一般不需要修改port = 3306 # 端口号socket = /var/lib/mysql/mysql.sock # 套接字文件 ...

  2. 进阶系列(2)—— C#集合

    一.集合介绍 集合是.NET FCL(Framework Class Library)的重要组成部分,我们平常撸C#代码时免不了和集合打交道,FCL提供了丰富易用的集合类型,给我们撸码提供了极大的便利 ...

  3. Reaction to 构造之法 of Software Engineering From The First Chapter toThe Fifth Chapter(补充版)

    几个星期前,我阅读过一篇文章,一位老师教导自己的学生要积极地去阅读文学文献,其中,我很欣赏他的一句话:“Just think of liturature as if you're reading a ...

  4. 消息队列第二篇:MessageQueue实战(课程订单)

    上一篇:消息队列介绍 本篇一开始就上代码,主要演练MessageQueue的实际应用.用户提交订单(消息发送),系统将订单发送到订单队列(Order Queue)中:订单管理系统(消息接收)端,监听消 ...

  5. 循环队列的C语言实现

    生活中有很多队列的影子,比如打饭排队,买火车票排队问题等,可以说与时间相关的问题,一般都会涉及到队列问题:从生活中,可以抽象出队列的概念,队列就是一个能够实现“先进先出”的存储结构.队列分为链式队列和 ...

  6. Intellij IDEA中file size exceeds configured limit解决

    把Hadoop源码导入IDEA中后,其中有个ClientNamenodeProtocolProtos文件代码高达82997行,IDEA直接就不把它当java类看了,报file size exceeds ...

  7. Windows上MyEclipse2017 CI7 安装、破解以及配置

    一.安装环境与安装包 操作系统:win7 MyEclipse2017 CI7下载地址:链接:https://pan.baidu.com/s/1TWkwntF9i5lOys3Z96mpLQ MyEcli ...

  8. 30行js让你的rem弹性布局适配所有分辨率(含竖屏适配)(转载)

    用rem来实现移动端的弹性布局是个好主意!用法如下: CSS @media only screen and (max-width: 320px), only screen and (max-devic ...

  9. 微信小程序配置文件记录

    最近公司要求,需要研究微信方面的问题,我有幸被选中了,一周时间,研究透做出个小程序来.我就从简单的开始了,记录一下,以后忘了,好来翻阅 app.json 配置文件 配置文件上写:是由哪些页面组成,配置 ...

  10. VMWare之——宿主机与虚拟机互相ping通,宿主机ping通另一台机器的虚拟机

    版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明出处:http://blog.csdn.NET/l1028386804/article/details/52267554 今天给大家带来 ...