iOS之UIScrollview添加约束图文详解

iOS之UIScrollview添加约束图文详解

原文链接 http://www.jianshu.com/p/e4a12061776d

前言

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

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

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

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

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

木有报错,很easy的事情

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

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

注意

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

scrollView在加载时,会自动根据内部子控件来计算contentSize的值(仅指通过xib\sb加载的控件,代码创建的不考虑在内)。

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

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

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

UIScrollview添加约束的正确方式

假设我们要实现如下效果

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

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

傻瓜级

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

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

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

特别注意

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

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

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

没有报错,噢耶,以后想添加什么子控件就往唯一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)+ 下面的间距,如图

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

不改就会这样

  • 1.实际内容小于唯一view高度

    多出滚动区域

  • 2.实际内容大于唯一view高度

    拖不上去

正常级

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

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

大神级

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

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

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

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

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

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

接下来添加最后一个控件

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

  • 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确定,最后来看看运行效果。

时间: 2024-08-03 13:36:27

iOS之UIScrollview添加约束图文详解的相关文章

微店怎么上架产品 微店添加商品图文详解教程

微店添加商品步骤 1.打开"微店"APP,点击[我的微店]进入我的微店页面,然后点击右上角[添加]进入添加商品页面. 2.在添加商品页面可以添加商品图片,填写商品描述.商品价格.商品库存等.商品图片可以添加多张,第一张上传的图片将作为此商品的头图,所有上传的图片都会出现在商品详情介绍中. 3.点击右上角[完成],商品就添加成功啦!这里可以将这个商品直接分享给微信好友.微信朋友圈.微博.QQ好友等,也可以继续添加或者预览商品.商品添加成功后,"我的微店"页面就会显示刚

为excel vba中添加、删除模块并插入全过程图文详解

  为excel vba中添加.删除模块并插入全过程图文详解         方法/步骤 1.点按快速启动栏excel 程序图标 进入excel 界面 点击选中任意单元格 然后按alt+f11 进入vbe界面 2.点击菜单栏 插入命令 在弹出的活动菜单中点按模块命令 3.另一种方式插入模块的方法可以在工程资管管理器中鼠标点击空白处 右键单击鼠标 在弹出的快捷菜单中选择插入命令 二级菜单中选择模块命令 4.如图所示模块1.模块2分别是通过菜单栏插入命令 和工程资源管理器点击右键创建的模块 5.如果

.Net Core 之 Ubuntu 14.04 部署过程(图文详解)_实用技巧

本篇文章主要介绍了.Net Core 之 Ubuntu 14.04 部署过程(图文详解) No.1 准备应用程序 1. 创建.Net Core Web项目 2. 使用VS2015发布 No.2 安装.Net Core for Ubuntu Ubuntu的安装就不介绍了.本人用的VMWare,装好Tools很方便. 具体安装步骤请参照:http://www.jb51.net/os/248849.html 1. 添加dotnet源 sudo sh -c 'echo "deb [arch=amd64]

Cocos2d-x win7 + vs2010 配置图文详解

Cocos2d-x win7 + vs2010 配置图文详解(亲测)   下载最新版的cocos2d-x.打开浏览器,输入cocos2d-x.org,然后选择Download,本教程写作时最新版本为cocos2d-1.01-x-0.9.1,具体下载位置如下图: 下载完之后,解压到当前文件夹.我把下载的程序放在F盘根目录,解压完毕之后,双击打开文件夹,看看里面有什么东西,红圈部分就是我们要安装使用的文件: 接下来,我们正式安装cocos2d-x到win7中去. 首先,双击上图中的cocos2d-w

SQL Server 2016 Alwayson新增功能图文详解

概述 SQLServer2016发布版本到现在已有一年多的时间了,目前最新的稳定版本是SP1版本.接下来就开看看2016在Alwyson上做了哪些改进,记得之前我在写2014Alwayson的时候提到过几个需要改进的问题在2016上已经做了改进. 一.自动故障转移副本数量 在2016之前的版本自动故障转移副本最多只能配置2个副本,在2016上变成了3个. 说明:自动故障转移增加到三个副本影响并不是很大不是非常的重要,多增加一个故障转移副本也意味着你的作业也需要多维护一个副本.重要程度(一般).

图文详解OpenTLD平台的搭建

图文详解OpenTLD平台的搭建 本文以图文的方式详解了OpenTLD平台的搭建.硬件平台:装有Windows 7/8/XP的电脑一台:软件平台:OpenTLD.OpenCV.Visual Studio 2010. 1.软件下载 OpenTLD:https://github.com/arthurv/OpenTLD/tree/master OpenCV:http://opencv.org/downloads.html 下载后如下图: 对OpenCV解压:双击=>点击Extract: 再对OpenT

图文详解Android属性动画_Android

 Android中的动画分为视图动画(View Animation).属性动画(Property Animation)以及Drawable动画.从Android 3.0(API Level 11)开始,Android开始支持属性动画,本文主要讲解如何使用属性动画.关于视图动画可以参见博文<Android四大视图动画图文详解>. 一.概述 视图动画局限比较大,如下所述: 1.视图动画只能使用在View上面. 2.视图动画并没有真正改变View相应的属性值,这导致了UI效果与实际View状态存在差

VMware使用方法(图文详解)_VMware

VMware 8虚拟机+汉化包+注册机下载地址:http://www.jb51.net/softs/377756.html 可用序列号: MV4YN-0L38Q-2ZK60-XUA7K-AAZ18(用下载的注册机生成序列号也可) 安装视频教程,个人不建议进行汉化,当然汉化后正常操作问题也不会太大 安装好之后就可以看到软件的主界面了(我没有汉化,所以界面是全英文,已汉化过的友友照着图的对应位置点击即可) 首先讲的当然是如何创建虚拟机 先在Home界面单击"Create a New Virtual

图文详解Ubuntu下安装配置Mysql教程_Mysql

Ubuntu安装Mysq有l三种安装方式,下面就为大家一一讲解,具体内容如下 1. 从网上安装 sudo apt-get install mysql-server.装完已经自动配置好环境变量,可以直接使用mysql的命令. 注:建议将/etc/apt/source.list中的cn改成us,美国的服务器比中国的快很多. 2. 安装离线包,以mysql-5.0.45-linux-i686-icc-glibc23.tar.gz为例. 3. 二进制包安装:安装完成已经自动配置好环境变量,可以直接使用m