iOS autoLayout总结

本文转自 http://ruikq.github.io/ios/autolayout/uiscrollview/2015/01/27/iOS-autolayout%E6%80%BB%E7%BB%93.html

 autolayout, and uiscrollview

之前学习iOS的时候没怎么接触过autoLayout,自从iPhone6个6+出来以后一直在为之前的app作适配,因此使用了大量的autoLayout作适配,一开始很不习惯,可是越用越以为好用,接触到如今遇到不少问题,在这里总结一下,包括三部分:限制的优先级、autoLayout下得UIScrollView和UITableView。html

优先级

在一开始autoLayout的使用过程当中,优先级经常是被我所忽略掉的,因此有的时候在一些稍微复杂的布局中每每会出现一些很奇怪的问题和警告,尤为是布局一些大小随内容改变的控件时(UIButton、UILabel、UIImageView),而这些问题和警告均可以经过优先级来解决,下面以UILabel为例子来总结一下:ios

图1

以上是UILabel的限制,都是采用默认的优先级,当点击长文字按钮的时候label上附有长文本,点击短文字按钮则是短的文本。git

首先看一下Content Hugging Priority如下部分,一开始使用autolayout的时候我是没有关注到这一部分的。Content Hugging Priority的的意思是限制内容变大优先级,下面对应横向和纵向,Content Compression Resistance Priority是限制内容缩小优先级,最下面的Intrinsic Size则是设置内容固定大小。github

为更好理解上述术语的意思,demo中只关注了横向。运行demo不管点击长文字仍是短文字按钮label的大小都是不会改变的。下面经过改变一些优先级来使label大小随文字大小改变,首先将label的Trailing的限制优先级改成700,其余不变,而后运行,发现label可随文字变大但不能变小,这是由于label的右边距离父视图的优先级700小于750,因此Trailing Constrain失效,限制内容变小的限制生效,因此当label内容变多时就限制住label变小,可是Content Hugging Priority的优先级为251小于700,当文字少时没法阻止label变大,如今改变Content Hugging Priority为800。objective-c

图2

出现警告,指望label宽度0,是由于在storyboard设计阶段自动计算label文字宽度为0,因此label大小也为0;能够经过设置Intrinsic Size 为PlaceHolder去掉警告,这里告诉storyboard设置一个临时占位尺寸,这个占位尺寸仅在storyboard设计阶段有效,不会影响到运行时的尺寸,运行,如今正常了。app

图3

UIScrollView

autoLayout下,UIScrollView的contentSize是由其中的内容大小来决定的,依赖关系和正常的子视图依赖父视图是相反的,因此UIScrollView的子视图的布局约束是不能够经过UIScrollView来肯定的,因此通常状况下的约束到了UIScrollView中就会出现不少错误和警告。布局

要处理这种状况就去要肯定UIScrollView中子视图的宽和高,可是这又和autoLayout下宽、高的可变性冲突,目前的方法是引进一个锚点视图,子视图的宽和高根据锚点视图肯定。post

图4

anchorViewForWidth是一个宽和父视图相等,高为0的视图,contentView的高固定、宽度和anchorViewForWidth相等,咱们也必须设置contentView的top、trailing、leading、button,这不影响contentView的大小,这至关因而UIScrollView可滚动区域的旁白,因此像这样在通常视图中看上去重复设定限制会发生警告,但在这里就不会出现。学习

在纵向滑动的UIScrollView项目中contentView的宽度依赖能够这么设置,上面的contentView的高度咱们是固定的,但若是高度是随运行时肯定的咱们就不能够设置固定了,在ios8中像UILabel、UIButton、UIImageView这类大小随内容改变的控件咱们是不须要设定高度,系统会自动根据内容计算,若是控件中的内容是动态得到的,咱们能够设定placeHolder占位尺寸来进行预设定;ui

图5

设置placeHolder以后

图6

而对于系统没法计算的控件虽然设置了placeHolder没有了警告,可是运行时控件却不可见,因此只有先设定高度固定再将限制映射为变量,运行时计算修改constant。

图7

UIScrollView中的注意事项

一、有些状况下UIScrollView不能滚动 缘由是使用autoLayout以后,在ViewDidLoad以后,系统会从新计算控件的一些值会致使UIScrollView的ContentSize变为(0,0),因此须要在viewDidLayoutSubViews方法中从新设置UIScrollView的contentSize,但有时在ios7上不行,ios7须要在viewDidAppear:animated方法设置contentSize。

UITableView

在UITableView的cell中使用autoLayout,能够根据内容自己来计算cell的高度,在iOS8中只要将tableView.rowHeight设置为UITableViewAutomaticDimension,系统就会根据cell设定好的约束自动计算出高度,在iOS7中须要使用systemLayoutSizeFittingSize:方法来根据约束计算cell的Size,而在iOS6中咱们须要手动计算cell的高度。

UITableView使用autoLayout比UIScrollView要简单,惟一让我遇到麻烦的是tableHeaderView,在xib文件中加入tableHeaderView以后是没法改变他的位置的,也不可以使用autoLayout增长约束,这就没法动态的改变tableHeaderView的高度;在搜寻了StackOverflow以后发现不须要对tableHeaderView设置autoLayout,想要改变tableHeaderView的高度直接更改frame就能够了。

CGRect headerFrame = self.listView.tableHeaderView.frame; headerFrame.size.height = 47; self.listView.tableHeaderView.frame = headerFrame; [self.listView setTableHeaderView:headerView]; self.listView.contentOffset = CGPointZero;

对于将外部自定义的view做为tableHeaderView,不能将frame大小设置在自定义的view中,必须也要和上面同样从新设置frame,不然会出现tableHeaderView遮挡cell、tableHeaderView拉伸和显示不全等奇怪现象。

总结

autoLayout是ios6就提出来的东西,一开始由于体验差、操做烦用的人不多,可是之后的开发中它是必不可少的,由此我想到了Swift,虽然如今刚刚出现版本还不成熟,可是之后一定是慢慢替代Object_C的,由于苹果不会出一个鸡肋东西。接触autoLayout以来已经有好几个月了,也是适配不少UI,autoLayout是一个越用越顺手的东西,若是出现奇怪的问题就说明某个点尚未掌握,须要再去细细学习。最后附上demo代码

相关文章
相关标签/搜索