AutoLayout 与 UIScrollView的相遇是一个不可避免的场景,像UITableView、UIWebView这些都是继承于UIScrollView的,关于它们的autolayout布局大体一致,但还是会有略微不同,而我们这篇讨论的主要是其contentSize问题,所以就直接讲UIScrollView就OK了。

如上图,我们将view分为3个部分,上面一部分主要用于展示海报或者一些封面图片,中间部分用来展示一些基本的信息,比如商品页面的价格,销量,分类等比较重要的信息,下面用于展示一些额外的信息,比如推荐给用户的一些其它商品或者门店等信息。

我们先按之前讲的来添加一些contraints,看一下UIScrollView里面添加Constraints有什么区别没有。 先依次添加约束:

.为上面的橙色view与UIImageview添加高度与上下左右的边距约束。
.然后再添加中间蓝色view及其内容的高度与上下左右边距的约束。
.再添加UISegment的高度与上下左右边距的约束。
.再添加底部的UITableView的上下左右边距约束。

我们来看一下IB会怎么处理目前的约束:

Scroll View ,Need constraints for height
Scrollable Content Size Ambiguity, Has ambiguous scrollable content height
Missing Constraints, Need constraints for : width
Scrollable Content Size Ambiguity,Has ambigous content size

全是Scrollview的问题,而且意思基本上就是说IB无法确定ScrollView的宽度与高度,我们知道UIScrollView最重要的就是其contentSize的宽高了,如果这个无法确定,那scrollview就无法知晓可以滚动查看的区域。其实这仅仅是表象,IB不会因为contentSize的可见区域不确定而抱怨,因为它会有一个默认的可见区域就是其bounds,其实IB真正抱怨的是其内部的subViews的布局对于它的依赖,比如我们看最上面的橙色View相对于上、左、右的约束都相对于scrollview的。scrollview内部的subViews的约束全依赖于scrollview,这样子的话,问题就来了,Scrollview和UILabel、UIButton等这些控件一样都会根据内容调整其contentSize(autolayout布局模式中,UILabel这种控件都会根据内容对自身宽高进行调整),如果Scrollview要根据其subviews来调整自身的contentsize,而其subviews又要根据scrollview的contentsize调整自身的布局,是不是就矛盾了,就成了相互依赖了。

所以IB要求UIScrollview(当然包括继承于它的UITableview、UIWebview这些控件)的contentSize必须在布局时能够确定。

由于Scrollview的contentSize由其subviews确定,其subviews的布局依赖于其父视图Scrollview的边界。这个矛盾,要不解决前者问题,要不解决后者,即要么不让UIScrollView的contentSize由其subviews确定,要么就让ScrollView的subviews不依赖其contentSize(即Scrollview的边界)。很显然,我们只能选择后者,因为前者你无法改变,其实从宏观上来看,改变了一个就相当于改变了两个,其实二者并没有什么特别区别,都是同一个问题导致的。

既然我们想好了策略,就来试一下,如何才能让Scrollview的subviews不依赖于其边界呢? 我们首先不考虑subviews的复杂布局情况,我们先把subviews嵌入到一个我们自己添加的ContainerView中,从而把我们的布局任务简化成Scrollview与ContainerView二者的约束关系,所有之前的subviews我们都放在ContainerView中,则subviews的约束就会仅仅依赖于ContainerView了,这些subviews不再与scrollview有直接关系。

我们虽然简化了布局任务,但是还是无法绕过Scrollview的ContentSize的边界确定问题,我们前面已经知道了Scrollview的子视图不能依赖于ScrollView的边界,那我们就让其子视图不依赖于其边界即可。 国外有一个网友在遇到上面的问题的时候就咨询了Apple的工程师,结果他们画了40分钟才给出了解决方案,这说明Scrollview在autolayout中的使用真的不是那么简单。Apple的工程师给出的解决方案就是让我们的ContainerView建立一个与UIScrollview的父视图即我们的main view建立一个Equal Width,Equal Height约束,这样子ContainerView的宽高就不再依赖于ScrollView的边界了,但是ContainerView还是Scrollview的子视图,Scrollview的边界还是没有确定,我们还要为ContainerView添加与ScrollView的边界约束,用以帮忙ScrollView确定边界。

OK,我们建立了ContainerView与mainview的equal width与 equal height后,效果果然就是我们想要的。 关于Autolayout与Scrollview相遇的故事,我们就先讲到这里,关于布局的场景总是像国际象棋一样,有数不尽的步骤与结果,连Machine都可以为之苦恼,所以这里只是通过这么一个示例,让大家对autolayout的布局理念有一个更深入的认识,不要过多的去抓鱼,而要学会如何抓鱼,抓鱼的诀窍是什么,学习一门技术,大家都会有各自的体会与理解,从根本上去掌握技术的原理,以此来应对千变万化的场景才能事半功倍。

本文示例代码:本文Demo

为了更好的理解autolayout的原理,推荐阅读:

Apple工程师如何讲解AutoLayout的?
讲解视频地址:Cocoa AutoLaout Video,找名称为Cocoa Autolayout的那一个视频。

讲稿:Cocoa autolayout PDF

在Scrollview中使用AutoLayout的更多相关文章

  1. ScrollView中嵌套recycleView 出现的不显示,显示不全,终极解决方案

    最近公司项目中用到了ScrollView去嵌套recycleView, 最开始我天真的把recycleView直接放入scrollView中,结果可想而知,什么都不显示,瞬间懵逼,我心想应该是和嵌套L ...

  2. 解决在ScrollView中套用ListView显示不正常

    最近在设计Android程序时,因为需要在ScrollView中添加一个ListView列表来显示一些信息.刚开始并没有想太多,但添加进去后才发现ListView不论怎样定义都只能显示一行,显示效果很 ...

  3. scrollView中可以自由滚动的listview

    直接在scrollView中写listview等可滚动控件会出现子控件高度计算的问题,为了解决这个问题,找到的方案是重写listview中的onmeasure方法: @Override public ...

  4. scrollview 中嵌套多个listview的最好解决办法

    在scrollview中嵌套多个listview的显示问题. 只需要调用如下的方法传入listview和adapter数据即可. /** * 动态设置ListView组建的高度 */ public s ...

  5. Android ScrollView中的组件设置android:layout_height="fill_parent"不起作用的解决办法

    例子,在ScrollView下加入的组件,无论如何也不能自动扩展到屏幕高度. 布局文件. [html] <?xml version="1.0" encoding=" ...

  6. ScrollView中嵌套ListView显示

    想要ScrollView中嵌套显示ListView 需要自定义ListView 并重写onMeasure方法 重新计算  heightMeasureSpec的高度 int newHeight = Me ...

  7. 在代码中使用Autolayout – intrinsicContentSize和Content Hugging Priority

    我们继续来看在代码中使用Autolayout的话题.先说intrinsicContentSize,也就是控件的内置大小.比如UILabel,UIButton等控件,他们都有自己的内置大小.控件的内置大 ...

  8. 实现ScrollView中包含ListView,动态设置ListView的高度

    ScrollView 中包含 ListView 的问题 : ScrollView和ListView会冲突,会导致ListView显示不全 <?xml version="1.0" ...

  9. ScrollView中嵌入ListView,GridView冲突的解决(让ListView全显示出来)

    ScrollView中嵌入原生ListView或GridView,会出现ListView,GridView显示不全的问题. 解决方法:重新构造一个ListView或GridView,重写OnMeasu ...

随机推荐

  1. redis单机上部署集群

    一.安装单机redis  redis的安装:版本至少是3.2.8及其以上,这里以3.2.8版本为例说明 1.安装redis wget http://download.redis.io/releases ...

  2. GYM 101933I(贪心、大整数)

    我读题有问题呀,题目中到底哪里保证数据一定至少是2倍关系了Orz--然后既然题意就是保证了那贪心一下即可,因为如果当前这个大的不选,那剩下一堆逐渐小于上一代的1/2的,凑起来都不如这个大的,更别说答案 ...

  3. Codeforces Round #527-D1. Great Vova Wall (Version 1)(思维+栈)

    time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standa ...

  4. Kestrel服务器

    Kestrel服务器 什么是Kestrel服务器 Kestrel是开源的(GitHub提供的源代码),事件驱动的异步I / O服务器,用于在任何平台上托管ASP.NET应用程序.这是一个监听服务器和一 ...

  5. 从I/O事件到阻塞、非阻塞、poll到epoll的理解过程

    I/O事件   I/O事件 非阻塞I/O.在了解非阻塞I/O之前,需要先了解I/O事件 我们知道,内核有缓冲区.假设有两个进程A,B,进程B想读进程A写入的东西(即进程A做写操作,B做读操作).进程A ...

  6. (转)生产环境常见的HTTP状态码列表(老男孩整理)

    生产环境常见的HTTP状态码列表(老男孩整理) 原文:http://blog.51cto.com/oldboy/716294 ##################################### ...

  7. 将JWT与Spring Security OAuth结合使用

    1.概述 在本教程中,我们将讨论如何使用Spring Security OAuth2实现来使用JSON Web令牌. 我们还将继续构建此OAuth系列的上一篇文章. 2. Maven配置 首先,我们需 ...

  8. 在ubuntu 12.04上安装tomcat 7.40

    因为源上的版本问题,所以没有使用源上的自动安装包,老规矩,Tomcat 7.0.40 Core下载地址:http://mirror.bit.edu.cn/apache/tomcat/tomcat-7/ ...

  9. mysql导入sql文件错误#1044 - Access denied for user 'root'@'localhost'

    在我的个人知识管理中,经常用到mysql数据库,wordpress搭建的worklog.搜索测试数据.我blog的测试环境等.我在自己的电脑上整了WAMP(Windows Apache MySQL P ...

  10. dynomite:高可用多数据中心同步

    https://github.com/Netflix/dynomite Dynomite, inspired by Dynamo whitepaper, is a thin, distributed ...