利用storyBoard
尝试自动布局ScrollView
实际测试如下:
1 scrollView + imageView(Sizefit)
失败!
2 imageView修改:只有leading和TopSpace,然后再代码中添加打印:
1 | [self.view layoutIfNeeded]; // 此行之前的layout被计算 |
失败!again
原因分析:通过打印可看出,上述两种方法都无法给出contentSize
1 | 2015-03-11 11:27:32.577 ScrollTagDemo[2393:259138] 只是设置了scrollView的约束,<UIScrollView: 0x7aaf1a00; frame = (190 190; 220 220); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x788a1750>; layer = <CALayer: 0x78689bb0>; contentOffset: {0, 0}; contentSize: {0, 0}> |
3 imageView再修改,先使用代码:
1 | self.scrollView.contentSize = self.imageView.bounds.size; |
success!
此时的打印contentSize:1
2015-03-11 11:52:11.289 ScrollTagDemo[2460:266559] 设置了contentSize的frame之后,<UIScrollView: 0x7b885c00; frame = (190 190; 220 220); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x7b06a2e0>; layer = <CALayer: 0x7b064680>; contentOffset: {0, 0}; contentSize: {759, 966}>
所以原因的确是contentSize的问题,这种方式就是官方给出的所谓混合解决方式,但在layout中设置frame可是不常见的,在我看来这有悖于layout的实质,可用但值得商榷,那么就继续探索能够使用约束给出contentSize的方法。
再次修改imageView:
失败,again!
按理说,给定img的宽高,就应该有contentSize了,但遗憾的是木有😢1
2015-03-11 12:01:10.255 ScrollTagDemo[2525:271602] 设置了contentSize的frame之后,<UIScrollView: 0x7ca72600; frame = (190 190; 220 220); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x7c1926d0>; layer = <CALayer: 0x7c18cd80>; contentOffset: {0, 0}; contentSize: {0, 0}>
4 imageView再修改,这次在第二次的基础上尝试:
success!it works!
但是对比先前的
仅仅是把Trainling跟Bottom变成了0,0而已,it works!
由此可见:subView的约束是根据contentSize计算而来的,而不是scroll自己!
但是但是,打印的结果仍然是:1
2015-03-11 12:10:35.446 ScrollTagDemo[2556:281194] 设置了contentSize的frame之后,<UIScrollView: 0x7b075600; frame = (190 190; 220 220); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x7aa2a2f0>; layer = <CALayer: 0x7a8795f0>; contentOffset: {0, 0}; contentSize: {0, 0}>
肯定是打印的地方不对,到底在哪儿呢?再试试,通过自定义view,猜测是laySubViews,重写之后结果验证如下:1
2
3
4
5
6
7
82015-03-11 13:49:47.407 ScrollTagDemo[2846:353070] 设置了imageView后 <UIScrollView: 0x7bbaf000; frame = (190 190; 220 220); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x7c145be0>; layer = <CALayer: 0x7b62da80>; contentOffset: {0, 0}; contentSize: {0, 0}>
2015-03-11 13:49:47.407 ScrollTagDemo[2846:353070] 设置了contentSize的frame之后,<UIScrollView: 0x7bbaf000; frame = (190 190; 220 220); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x7c145be0>; layer = <CALayer: 0x7b62da80>; contentOffset: {0, 0}; contentSize: {0, 0}>
2015-03-11 13:49:47.412 ScrollTagDemo[2846:353070] -------------->
2015-03-11 13:49:47.413 ScrollTagDemo[2846:353070] timeOfLayout 1
2015-03-11 13:49:47.413 ScrollTagDemo[2846:353070] scrollView.contentSize:{0, 0}
<!-- 2015-03-11 13:49:47.413 ScrollTagDemo[2846:353070] --------------> -->
2015-03-11 13:49:47.413 ScrollTagDemo[2846:353070] timeOfLayout 2
2015-03-11 13:49:47.413 ScrollTagDemo[2846:353070] scrollView.contentSize:{759, 966}
在整个viewDidLoad中都没有计算contentSize,而是在结束之后由系统去view的 layoutSubviews方法中计算的<在iOS8之前是要自己去加上一句的>!
5 再测试:
imageView再添加约束,让其的w和h 跟 scrollView的w和h 相等
also worked!
打印输出:1
2
3
4
5
6
7
82015-03-11 15:52:42.841 ScrollTagDemo[3154:467930] -------------->
2015-03-11 15:52:42.841 ScrollTagDemo[3154:467930] timeOfLayout 1
2015-03-11 15:52:42.884 ScrollTagDemo[3154:467930] scrollView.frame:{{250, 190}, {100, 220}}
2015-03-11 15:52:42.884 ScrollTagDemo[3154:467930] scrollView.contentSize:{0, 0}
2015-03-11 15:52:42.885 ScrollTagDemo[3154:467930] -------------->
2015-03-11 15:52:42.885 ScrollTagDemo[3154:467930] timeOfLayout 2
2015-03-11 15:52:42.885 ScrollTagDemo[3154:467930] scrollView.frame:{{250, 190}, {100, 220}}
2015-03-11 15:52:42.885 ScrollTagDemo[3154:467930] scrollView.contentSize:{759, 966}
发现根本 scrollView.frame就没有变化,但是这明显与通常理解的矛盾,明明已经相等而数值不同,其实这就是系统针对scrollView做的特殊处理,其实并没有真正去加上这个约束,加的其实是:
finally
这就是scrollView的完整约束!这也就是在官方文档中所提到的“by creating constraints between the view and a view outside the scroll view’s subtree, such as the scroll view’s superview”
将这个所谓相等的约束引用更改,就能结合代码更改contentSize
脑洞:既然结果显示w和h可以设置为“>=”,是否意味着可以自己来设置这样的约束对方,没实验,不过估计即便可以也不会有人去这样设置的👌!……^_^