iOS之UIScrollview添加约束图文详解和实现复杂页面

声明:本文系转发记录,原文地址:https://www.jianshu.com/p/e4a12061776d

前言

在iOS开发中,autolayout是一个很强大的东西,用好了,能让你事半功倍,用不好,各种蛋疼。不过autolayout是很容易学的,笔者当时仅仅看了一个多小时的资料就轻松上手,相信比笔者厉害的大有人在。

不过无论多简单的东西,用起来总有不如意的地方,笔者曾经在UIScrollView的约束上折腾了很久,各种报错,各种查资料,终于在笔者不断的尝试下,找到了解决办法。我相信在工作中肯定有很多跟我一样,被它折腾的死去活来的同僚,在这里,笔者将自己的理解分享给大家。

我们先将约束分为以下几类(仅指子控件与UIScrollview之间的约束)

  • 1.间距类:既子控件到父控件上下左右的间距
  • 2.宽高类:既子控件与父控件的宽高比
  • 3.居中类:既子控件在父控件中水平或者垂直居中

首先我们来看一个例子,在普通View上给子控件添加约束

image
image

木有报错,很easy的事情

接下来再看看在UIScrollView上给子控件添加约束的例子

image
image

纳尼?同样的约束,竟然报错了,以笔者最初的理解,明明都告诉它到上下左右的间距了,为什么还会报错,难道是Xcode的bug?

注意

在autolayout中,所有的间距类约束,并非相对于父控件本身的,而是相对于父控件的内容视图的(比如UIScrollview的contentSize),由于普通view的内容视图与本身大小一样,所以可以看成相对于它自身

scrollView在加载时,会自动根据内部子控件来计算contentSize的值。

看完上面两句话,相信大家应该知道为什么会报错了吧,子控件的frame依赖了scrollview的contentSize,而contentSize的值又要根据子控件的frame来计算,那到底该怎样?所以Xcode懵了......

在开发中我们可能会遇到这样的情况,在viewDidLoad中设置了scrollview的contentSize,但是当程序运行时,并不是自己想要的效果,就是因为scrollview根据内部子控件重新计算了contentSize的值,因此我们可以在viewDidAppear中来进行设置

说了这么多,那我们怎么来解决这个问题呢?废话不多说,直接开撸

UIScrollview添加约束的正确方式

假设我们要实现如下效果

image

首先添加UIScrollview到控制器view上,添加约束(这个不用笔者教吧,笔者这里是上下左右间距为0,所以运行后UIScrollview的大小与屏幕大小一样)

这里只讲竖直滚动,水平不滚动的情况,其他情况类似,笔者相信各位的智商

傻瓜级

给UIScrollView添加一个唯一的子控件UIView(约束如下图所示),把这个view看成是scrollview的内容视图(暂且称它“唯一view”),以后所有的子控件都添加到这个view里面

image

到父控件上下左右的间距固定(0是随便写的,自己根据需求决定),固定view的高度(800随便写的),加完约束后情况

image

报错,正常,报错是因为水平方向没有确定,垂直方向是没有问题的。笔者先来解释下上面约束的含义,唯一view到scrollview内容视图的上下左右间距都是0,并且固定高度为800,那么scrollview会自动计算出contentSize.height = 0(上间距) +800 + 0(下间距) = 800,那么水平方向呢?contentSize.width = 0(左间距) + 宽度? + 0(右间距) = ?,条件不足,无法计算

特别注意

网上有资料显示,间距类约束其实是在设置scrollView的内边距,经过笔者的亲自验证,这种说法是不对的,笔者将间距都设置为10,然后运行程序打印了scrollView.contentInset,结果显示都是0,且contentSize宽高都多了20,所以间距是算在contentSize里的,并非contentInset

接下来我们再来添加一个约束

image

让唯一view与scrollview等宽,再看结果

image

没有报错,噢耶,以后想添加什么子控件就往唯一view里添加吧,相对于唯一view添加约束就so easy了。

也许大家会有个疑问,唯一view与scrollview等宽,那到底是多宽,不还是依赖于contentSize么?

注意

宽高类约束是相对于scrollview本身的,并非相对于它的内容视图的,所以scrollview有多宽,唯一view就有多宽,与contentSize无关

至此,scrollview的contentSize就可以确定其大小了
contentSize.height = 0(上间距) +800 + 0(下间距) = 800
contentSize.width = 0(左间距) + 唯一view宽 + 0(右间距) = 唯一view宽(scrollview\控制器view\屏幕宽度)

看这里!!!!

记得把800改了,改成最后一个按钮的最大Y值(Y + height)+ 下面的间距,如图

image

如果在运行时才能确定最后按钮的最大Y值,可以通过代码修改唯一view的高度约束

正常级

与傻瓜级类似,只是scrollview的唯一view不再固定高度,而是根据它内部的子控件的约束自动调整,如图

image

我们看最后一个按钮的约束,上左右间距+固定高度已经可以确定其位置和大小了,为什么还要加个下间距?就是为了确定父控件唯一view的高度,这里唯一view的高度 = 按钮最大Y值 + 下间距

大神级

不要那所谓的唯一view,直接在scrollview里面添加子控件
先添加第一个子控件(称它为“子1”)及约束

image

子1距离scrollview的内容视图,上间距为10,左右间距为0

image

子1与scrollview等宽,它的高度是根据它内部子控件约束确定的,这里就不贴图了,会autolayout的应该都会,不理解的就当做是固定高度,此时它的位置跟尺寸已经确定,同时scrollview.contentSize.width = 0(左间距) + 子1宽度 + 0(右间距) = 子1宽度(就是scrollview\控制器view\屏幕宽度)。

报错是因为没有设置子1到scrollview内容视图的下间距,暂时不管它(如果看着不爽,可以先添加一个下间距约束,最后记得删除),继续往scrollview中添加下面的子视图,添加完后的效果图

image

下面控件的约束都一样(不贴图了)

  • 与上面视图的垂直间距为10
  • 到scrollview的内容视图左右间距为0
  • 固定高度
    约束还是报错,报错原因与添加子1一样

接下来添加最后一个控件

image

搞定,木有错误了,我们来看看约束

  • 1.上间距为10,前面控件的位置与尺寸已经确定
    按钮Y值 = 上一个控件的最大Y值 + 10
  • 2.左右间距为10,前面已经确定了scrollview内容视图的宽度
    按钮宽度 = 内容视图宽度 - 2 * 10
    按钮X值 = 10
  • 3.固定高度40
    按钮高度 = 40
    上面的约束已经确定了按钮的frame,那么最后一个下间距就是为了确定scrollview.contentSize.height
    scrollview.contentSize.height = 按钮的Y值 + 按钮的高度 + 下间距

到目前为止,所有子控件位置大小确定,scrollview的contentSize确定,最后来看看运行效果。

image

小伙伴们学会了吗,笔者初次分享经验,不喜勿喷,有错误或者不理解的地方可以留言

作者:codingZero
链接:https://www.jianshu.com/p/e4a12061776d
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容