使用Masonry在UIScrollView内布局
理论分析
首先,我们知道Autolayout改变了传统的以frame为主的布局思想。它其实是一种相对布局,核心思想是视图与视图之间的位置关系。比如,我们可以根据矩形的起始横坐标、纵坐标、长和宽这四个变量确定它的位置。或者,如果已经确定矩形A的位置,只要知道矩形B每条边的和A对应边之间的距离,也能确定B的位置。前者就是frame的思想,它基于绝对数值,而后者是Autolayout的思想,它基于偏移量的概念。
其次,UIScrollView有自己的frame也就是我们在屏幕上能看到的区域。它还有一个contentSize的概念。在使用frame布局的时候,我们一般先设置好子视图的位置,最后再设置contentSize,它会将所有的子视图包含在内。于是通过滑动,我们就可以在有限的布局中,看到所有的内容了。
但是在Autolayout时代,为了简化布局,我们希望contentSize能够自动设置。比如有一个scrollView,它有两个子视图。frame分别为(x: 0, y: 0, width: 10, height: 10)和(x: 10, y: 0, width: 10, height: 10),那么我们自然会认为这两个视图左右并排排列,contentSize为(x: 0, y: 0, width: 20, height: 10):
这种把若干个子视图合并,得出contentSize的能力,人类是天生具备的,但是计算机却不是这样。仅凭以上信息,程序无法推断出真正的contentSize。原因在于,我们没有明确的告诉系统,在这两个子视图拼接而成的区域以外,还有没有区域应该被contentSize包含。
也就是说,contentSize也有可能是下图中的阴影部分:
如果需要指定contentSize就是两个正方形拼接而成的区域,我们还需要提供四个信息:
- 左边的正方形的左侧的边,距离contentSize左边的距离为0
- 右边的正方形的右侧的边,距离contentSize右边的距离为0
……
通过以上的分析,我们可以看到,其实contentSize是依赖于子视图自身的大小,和上下左右四个方向的留白大小计算出的。而UIScrollView的leading/trailing/top/bottom是相对于它的contentSize而不是bounds来确定的。所以如果你写这样的代码,布局是肯定不会生效的:
subview.snp_makeConstraints { (make) -> Void in
make.edges.equalTo(scrollView).offset(5)
}
因为我们其实是在根据UIScrollView的leading/trailing/top/bottom来确定子视图的位置,而我们已经分析过,UIScrollView的leading/trailing/top/bottom是相对于自己的contentSize而言的。而contentSize又是根据子视图位置决定的。这就变成了一种你依赖我,我又依赖你的情况。
为了打破这种循环依赖,为子视图添加约束的两个要求是:
- 它不依赖于任何与scrollview有关布局,也就是不能参考scrollview的位置和大小。
- 它不仅要确定过自己的大小,还要确定自己与contentSize四周的距离。
第二个要求意思是说,正常使用autolayout时,我们确定一个矩形在水平方向上的范围,只要知道它的左边距离它左边的矩形有多远,以及它有多宽即可。但是在UIScrollView中布局时,还需要告诉UIScrollView,它的右边距离右边的视图有多远。这样contentSize才能确定。否则UIScrollView就不知道contentSize向右可以延伸多少。在竖直方向上也是同理。
这两大要求一定要牢记!接下来我们的代码都将围绕如何满足这两大要求展开。
动手实践
明白了问题的理论背景后,我们通过一个具体的需求,来看看正确的代码怎么写,以下面这个效果为例:
如图所示,中间是一个UIScrollView,它的背景颜色是黄色。红色部分我们称之为box,它是一个普通的,红色背景的UIView。也就是说我们向UIScrollView中添加了多个box,每个子box之间间隔一定距离。我们分步实现这个功能
使用container
首先我们介绍一种使用Container的方法。
第一步:为scrollView添加约束
let scrollView = UIScrollView()
view.addSubview(scrollView)
scrollView.snp_makeConstraints { (make) -> Void in
make.centerY.equalTo(view.snp_centerY)
make.left.right.equalTo(view)
make.height.equalTo(topScrollHeight)
}
我们之前说过,使用Autolayout时,不用考虑frame布局。所以直接创建一个scrollView对象。需要先把scrollView添加到父视图上才能添加约束。
对scrollView添加约束没有什么难点,就像我们给其他视图添加约束一样。这里表示scrollView和父视图左右对齐,居中显示。
第二步:为container添加约束
scrollView.addSubview(containerView)
containerView.snp_makeConstraints { (make) -> Void in
make.edges.equalTo(scrollView)
make.height.equalTo(topScrollHeight)
}
这里对container的约束非常重要,第一个约束表示自己上、下、左、右和contentSize的距离为0,因此只要container的大小确定,contentSize也就可以确定了,因为此时它和container大小、位置完全相同。
第二个约束直接通过一个数值,确定container的高度。避免了依赖scrollview布局。这样一来,scrollview就变成水平的了。container的宽度直接决定了scrollview的宽度。
使用Masonry在UIScrollView内布局的更多相关文章
- 使用Masonry对UIScrollView自动布局
之前使用Masonry对UIScrollView进行过约束,当时是遇到了问题的,怎么约束都不对,因为赶进度直接改用frame了也没有对问题深究.就这样过了很久.........,直到前一段换工作的时候 ...
- UIScrollView的布局
一.UIScrollView的子控件布局不能跟其它的控件一样进行布局,因为UIScrollView会根据子控件计算出ContentSize的大小,那么我们应该如何进行布局呀. 遵循以下两点就行 1.参 ...
- iOS开发之--Masonry多个平均布局
使用Masonry平均布局,代码如下: 1.创建 // 图片组数 NSArray *imgAry = @[@"home_icon01",@"home_icon02&quo ...
- IOS开发之UIScrollView约束布局
概要 在iOS开发学习中,UIScrollView是绕不过去的一个重要控件. 但是相对于Android的ScrollView,iOS的这个滚动控件的用法简直是复杂一万倍... 最主要是目前能找到的大部 ...
- jQuery Masonry构建pinterest网站布局注意要点(转)
在愚人码头的博客上看到有关于如何构建pinterest网站的文章,其实就是“图片瀑布流显示”,我试着在本地做了一个,没有什么问题,但是放到公司的网站上就问题多多.一是定位不准确,二是图片显示不完整.但 ...
- iOS学习——布局利器Masonry框架源码深度剖析
iOS开发过程中很大一部分内容就是界面布局和跳转,iOS的布局方式也经历了 显式坐标定位方式 --> autoresizingMask --> iOS 6.0推出的自动布局(Auto La ...
- 用Maonry如何实现UIScrollView
一,使用UIScrollView 与其他View 布局不同的地方在于, ScrollView的高度/宽度不固定: ScrollView的高度和宽度由其内容决定(即 Scroll View 的 cont ...
- Masonry自动布局与UIScrolView适配
Masonry介绍 Masonry是一个轻量级的布局框架 拥有自己的描述语法 采用更优雅的链式语法封装自动布局 简洁明了 并具有高可读性 而且同时支持 iOS 和 Max OS X.可以通过cocoa ...
- 布局神器:Flexbox
最近的工作内容大多是移动端网页的开发,百分比布局,Media Queries,Bootstrap等常规的响应式/自适应的开发技术皆一一试过,但觉以上都不够灵活,所以,一直再尝试寻求更加灵活的精确的移动 ...
随机推荐
- HDU-1864:最大报销额(浮点数01背包)
链接:HDU-4055:最大报销额 题意:现有一笔经费可以报销一定额度的发票.允许报销的发票类型包括买图书(A类).文具(B类).差旅(C类),要求每张发票的总额不得超过1000元,每张发票上,单类物 ...
- 接口测试工具Postman接口测试图文教程
Postman接口测试工具使用 一.前言 在前后端分离开发时,后端工作人员完成系统接口开发后,需要与前端人员对接,测试调试接口,验证接口的正确性可用性.而这要求前端开发进度和后端进度保持基本一 ...
- 会声会影2018提示dll文件丢失怎么办?
一些会声会影2018用户,在安装.使用软件的过程中,会出现dll缺失的提示,导致软件无法打开,那么,出现这一问题要怎么解决.接下来小编为大家具体介绍下两种解决方法. 图1:dll丢失提示 打开会声会影 ...
- leetcode个人题解——#36 valid Sudoku
思路题目里已经给出来了,判断是否是一个有效数独,只需满足以下三个条件: 1.同行元素不重复且1-9都有: 2.同列元素不重复且1-9都有: 3.每个粗线分隔的3*3的小九宫格元素不重复且1-9都有. ...
- HTML页面模板代码
作者声明:本博客中所写的文章,都是博主自学过程的笔记,参考了很多的学习资料,学习资料和笔记会注明出处,所有的内容都以交流学习为主.有不正确的地方,欢迎批评指正 HTML页面模板代码 常用的页面模板 & ...
- Python Requests库简单入门
我对Python网络爬虫的学习主要是基于中国慕课网上嵩天老师的讲授,写博客的目的是为了更好触类旁通,并且作为学习笔记之后复习回顾. 1.引言 requests 库是一个简洁且简单的处理HTTP请求的第 ...
- YQCB冲刺周第一天
团队讨论的照片 任务看板为 今天小组成员讨论了每个页面的排版,每个页面的跳转,以及页面的排版. 今天准备编写登录界面的.注册界面的代码. 遇到的困难是用户记账时选择的分类标准很多,最后将其整合,删减.
- 查看dll依赖项
win7 系统: 开始-->所有程序->vs2012文件夹->vs tools->对应的命令提示符 输入命令: dumpbin /dependents 你的文件(可以是exe, ...
- 【IdentityServer4文档】- 术语&演示服务器和测试
术语 你需要了解一下,规范.文档和对象模型使用的术语有哪些. IdentityServer IdentityServer 是一个 OpenID Connect 提供程序 - 它实现了 OpenID C ...
- DP--HDU 1003(最大子串和)
问题描述: 给定整数A1, A2,--AN (可能有负数),求I到j的最大值. 例如: -2, 11, -4, 13, -5, -2时答案为20 对于这个问题的算法 ...