UIScrollview 与 Autolayout 的那点事
原文 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 的那点事的更多相关文章
- 示例详解:UIScrollview 与 Autolayout 的那点事
前言 自从写了介绍Masonry那篇文章以后 就一直有人对UIScrollView的那个例子不是很理解 UIView *container = [UIView new]; [scrollView ad ...
- UIScrollView在AutoLayout下的滚动问题
使用Storyboard编写UI,设置支持AutoLayout. 在其中的一个场景上,添加一个UIScrollView,在对应的代码里增加 - (void)viewDidLoad { [super v ...
- UIScrollView使用autolayout 垂直滚动
转自:http://dadage456.blog.163.com/blog/static/30310744201491141752716 1.创建一个空白的UIViewController .将UIS ...
- UIScrollView的AutoLayout约束
首先UIScrollview包含自身的frame和contentSize二个部分.frame决定其展示给用户的可见区域,contentSize决定其整个内容的大小.如果frame的宽高小于conten ...
- iOS UIScrollView使用Autolayout
最近项目在迭代更新的时候,需要在之前用Autolayout写的界面里添加一个button,添加完这个button后,iPhone5,iPhone4显示不全了.遇到整个问题后很自然就想到了用UIScro ...
- iOS— UIScrollView和 UIPageControl之间的那些事
本代码主要实现在固定的位置滑动图片可以切换. 目录图如下: ViewController.h #import <UIKit/UIKit.h> // 通过宏定义定义宽和高 #define W ...
- Storyboard中使用UIscrollView添加约束的开发总结
第一次在项目中用storyboard做界面,一般的界面直接添加约束非常爽快 然后有个界面有scrollview,添加了约束还总是出错 刚开始使用了 wCompact,hRegular,滑动出现问题,有 ...
- 【原】Masonry+UIScrollView的使用注意事项
[原]Masonry+UIScrollView的使用注意事项 本文转载请注明出处 —— polobymulberry-博客园 1.问题描述 我想实现的使用在一个UIScrollView依次添加三个UI ...
- iOS autoLayout总结
本文转自 http://ruikq.github.io/ios/autolayout/uiscrollview/2015/01/27/iOS-autolayout%E6%80%BB%E7%BB%93. ...
随机推荐
- 关于go语言中的WaitGroup
如果你刚接触Go语言并且想用它构建高并发,高性能的应用,弄明白WaitGroups是怎么回事很重要. 在本教程中,我们将掌握以下内容: WaitGroups的用途 一个WaitGroups的简单示例 ...
- Vs2012 编写代码规则
FxCop编写规则 VS2012 下更方便,所需的DLL在: D:\Program Files (x86)\Microsoft Visual Studio 11.0\Team Tools\Static ...
- 看oracle的sid
ps -ef|grep pmon 可以从进程名字里看到 也可以通过 sqlplus / as sysdbashow parameter instance_name
- Dao DaoImp
DAO层:DAO层主要是做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此,DAO层的设计首先是设计DAO的接口,然后在Spring的配置文件中定义此接口的实现类,然后就可在模块中调用此接口 ...
- 《JavaScript》字符转义
escape/unescape encodeURIComponent/decodeURIComponent encodeURI/decodeURI 转义函数会对一些 特殊字符进行转义编码 英文.数字. ...
- 软工大作业DB天气项目风险评估
风险 发生概率 损失 风险度 解决方案 项目延期 80% 浪费时间,项目完成进度降低,考试得分低 79% 提前做好详细的准备工作,各方面做好沟通. 工作效率低下 30% 影响进度,使项目延期. 85% ...
- mvc 路由配置-学习2
public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { r ...
- eg_8
问题描述:比较两数组是否相等 Demo_1: import java.util.Arrays; public class TestArray { public static void main(Str ...
- spring时间管理
spring时间管理相比Quartz要简单的多,但功能不如quartz强大 spring.xml的配置 <?xml version="1.0" encoding=" ...
- OSG学习:计算纹理坐标
在很多时候,直接指定纹理坐标是非常不方便的,如曲面纹理坐标,只有少数的曲面(如圆锥.圆柱等)可以在不产生扭曲的情况下映射到平面上,其他的曲面在映射到表面时都会产生一定程度的扭曲.一般而言,曲面表面的曲 ...