參考鏈接:
Apple:
https://developer.apple.com/library/ios/technotes/tn2154/_index.html
在AutoLayout體系中,UIScrollView是一個(gè)特殊的視圖。我們先看一下官網(wǎng)的一些說明:
In general, Auto Layout considers the top, left, bottom, and right edges of a view to be the visible edges. That is, if you pin a view to the left edge of its superview, you’re really pinning it to the minimum x-value of the superview’s bounds. Changing the bounds origin of the superview does not change the position of the view.
大致意思是說,通常情況下,如果你設(shè)置一個(gè)視圖和其父視圖的邊距,這個(gè)邊距實(shí)際上是相對(duì)于父視圖的bounds而言的。注意這英文文檔中有一句話容易引起誤解:Changing the bounds origin of the superview does not change the position of the view,意思是改變父視圖的bounds的origin并不會(huì)改變視圖的position。如果深究這句話會(huì)偏離本文的主題,所以下面只是簡(jiǎn)單解釋一下:
做一個(gè)小Demo:
當(dāng)點(diǎn)擊Button按鈕的時(shí)候,讓父視圖(redView)的bounds的origin發(fā)生了變化,我們發(fā)現(xiàn)其子視圖(whiteView)向左發(fā)生了偏移,但是程序打印結(jié)果顯示:
2016-06-04 13:34:33.850 ChangeBounds[45808:3465767] 68.500000
2016-06-04 13:34:33.852 ChangeBounds[45808:3465767] 68.500000
也就是說,position沒有發(fā)生變化,但白色視圖的位置確實(shí)向左發(fā)生了偏移(偏移量為10)。白色視圖向左偏移是因?yàn)楦敢晥D(即紅色視圖)的bounds的origin由(0, 0)變成了(10, 0), 當(dāng)紅色視圖的origin發(fā)生變化后,其坐標(biāo)變化類似于:
這個(gè)解釋到此為止,因?yàn)閜osition是錨點(diǎn)anchorPoint在superLayer中的位置呢,錨點(diǎn)沒有發(fā)生變化,所以position也沒有變化,至于什么是錨點(diǎn),再扯就遠(yuǎn)了。
好,我們回到ScrollView和AutoLayout上來(lái)。
上面說到,通常情況下,如果你設(shè)置一個(gè)視圖和其父視圖的邊距,這個(gè)邊距實(shí)際上是相對(duì)于父視圖的bounds而言的。但是ScrollView有所不同,它的leading/trailing/top/bottom space是相對(duì)于UIScrollView的contentSize而不是bounds來(lái)確定的,所以如果用UIScrollView和它的subview的leading/trailing/top/bottom來(lái)互相決定大小時(shí),就會(huì)出現(xiàn)Has ambiguous scrollable content width/height的warning.
蘋果官網(wǎng)上也說道:
The UIScrollView class scrolls its content by changing the origin of its bounds. To make this work with Auto Layout, the top, left, bottom, and right edges within a scroll view now mean the edges of its content view.
所以上、下、左、右這些約束要相對(duì)于UIScrollView的contentView來(lái)設(shè)置。
所以我們要給這個(gè)UIScrollView對(duì)象添加一個(gè)contentView, 在故事板中可以往scroll view上托一個(gè)view, 注意這個(gè)view的上下左右約束都是0, 并且設(shè)置它的寬高約束,并Remove At build path, 通過這個(gè)content view告訴scroll view其content size. 步驟如下:
Step 1> 托入U(xiǎn)IScrollView,并設(shè)置其約束,比如上下左右
Step 2> 往這個(gè)Scroll view上托入一個(gè)view, 這個(gè)view的上下左右和scroll view的約束都是0,并設(shè)置其寬高和scroll view相同,對(duì)寬約束和高約束,設(shè)置Remove at build time
Step 3> 通過改變這個(gè)content view的寬高約束來(lái)改變scroll view的content size
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:self.contentView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:self.view.bounds.size.width];
[self.contentView addConstraint:widthConstraint];
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:self.contentView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:250];
self.heightConstraint = heightConstraint;
[self.contentView addConstraint:heightConstraint];
這個(gè)操作流程不好用文字來(lái)表達(dá)。以前錄個(gè)一個(gè)小視頻,可參見這里: http://pan.baidu.com/s/1kVnP0vt
肯定有需要補(bǔ)充和錯(cuò)誤的地方,若發(fā)現(xiàn)請(qǐng)聯(lián)系<mail://liuxing8807@126.com>]