2015-03-02 21 views
1

我的通知中心組件需要有基於它所包含的內容的動態高度。我有一個簡單的界面 - 一個UILabel下面有一個UICollectionView。 (根據我爲流佈局中的單元格提供的大小,集合視圖的高度會增加。)使用自動佈局指定動態通知中心小部件高度

要正確指定窗口小部件的高度,需要哪些約束?

我認爲這足以在標籤上提供Top約束來將其固定到視圖的頂部,指定集合視圖的頂部與標籤的底部對齊,然後爲集合視圖提供固定高度(即當itemSize更改時更新),然後將集合視圖的底部對齊到視圖的底部。但是這會導致兩個破壞的約束 - 集合視圖的高度和標籤與集合視圖之間的垂直約束。

let label = //... 
label.setTranslatesAutoresizingMaskIntoConstraints(false) 
self.view.addSubview(label) 
self.view.addConstraint(NSLayoutConstraint(item: label, attribute: .Top, relatedBy: .Equal, toItem: self.view, attribute: .Top, multiplier: 1, constant: 10)) 
self.view.addConstraint(NSLayoutConstraint(item: label, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .Height, multiplier: 1, constant: 25)) 
self.view.addConstraint(NSLayoutConstraint(item: label, attribute: .Leading, relatedBy: .Equal, toItem: self.view, attribute: .LeadingMargin, multiplier: 1, constant: 0)) 
self.view.addConstraint(NSLayoutConstraint(item: label, attribute: .Trailing, relatedBy: .Equal, toItem: self.view, attribute: .TrailingMargin, multiplier: 1, constant: 0)) 

let collectionView = //... 
collectionView.setTranslatesAutoresizingMaskIntoConstraints(false) 
self.view.addSubview(collectionView) 
self.view.addConstraint(NSLayoutConstraint(item: collectionView, attribute: .Leading, relatedBy: .Equal, toItem: label, attribute: .Leading, multiplier: 1, constant: 0)) 
self.view.addConstraint(NSLayoutConstraint(item: collectionView, attribute: .Trailing, relatedBy: .Equal, toItem: label, attribute: .Trailing, multiplier: 1, constant: 0)) 
self.view.addConstraint(NSLayoutConstraint(item: collectionView, attribute: .Top, relatedBy: .Equal, toItem: label, attribute: .Bottom, multiplier: 1, constant: 0)) 
self.view.addConstraint(NSLayoutConstraint(item: collectionView, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 1, constant: 0)) 
self.collectionViewHeightConstraint = NSLayoutConstraint(item: collectionView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .Height, multiplier: 1, constant: 100) 
collectionView.addConstraint(self.collectionViewHeightConstraint) 

//later on 
let flowLayout = collectionView.collectionViewLayout as UICollectionViewFlowLayout 
flowLayout.itemSize = //some new size 
self.collectionViewHeightConstraint.constant = flowLayout.itemSize.height * numberOfRows 

問題:

Unable to simultaneously satisfy constraints. 
"<NSLayoutConstraint:0x6080000998c0 V:|-(10)-[UILabel:0x6000001db300] (Names: '|':UIView:0x60800018f700)>", 
"<NSLayoutConstraint:0x608000099e60 V:[UILabel:0x6000001db300(25)]>", 
"<NSLayoutConstraint:0x60800009a2c0 V:[UILabel:0x6000001db300]-(0)-[UICollectionView:0x7ff94b02c200]>", 
"<NSLayoutConstraint:0x60800009a310 UICollectionView:0x7ff94b02c200.bottom == UIView:0x60800018f700.bottom>", 
"<NSLayoutConstraint:0x60800009a360 V:[UICollectionView:0x7ff94b02c200(100)]>", 
"<NSLayoutConstraint:0x60800009a4f0 'UIView-Encapsulated-Layout-Height' V:[UIView:0x60800018f700(667)]>" 
Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x60800009a360 V:[UICollectionView:0x7ff94b02c200(100)]> 

而且

Unable to simultaneously satisfy constraints. 
"<NSLayoutConstraint:0x6080000998c0 V:|-(10)-[UILabel:0x6000001db300] (Names: '|':UIView:0x60800018f700)>", 
"<NSLayoutConstraint:0x608000099e60 V:[UILabel:0x6000001db300(25)]>", 
"<NSLayoutConstraint:0x60800009a2c0 V:[UILabel:0x6000001db300]-(0)-[UICollectionView:0x7ff94b02c200]>", 
"<NSLayoutConstraint:0x60800009a310 UICollectionView:0x7ff94b02c200.bottom == UIView:0x60800018f700.bottom>", 
"<NSLayoutConstraint:0x60800009a4f0 'UIView-Encapsulated-Layout-Height' V:[UIView:0x60800018f700(0)]>" 
Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x60800009a2c0 V:[UILabel:0x6000001db300]-(0)-[UICollectionView:0x7ff94b02c200]> 
+0

顯示系統決定破壞哪個約束,但基本上是任意的。您需要顯示衝突的約束條件列表。 – 2015-03-07 09:27:55

+0

@KenThomases謝謝,更新 – Joey 2015-03-07 21:05:27

回答

0

變化self.view.addConstraint(self.collectionViewHeightConstraint)collectionView.addConstraint(self.collectionViewHeightConstraint),因爲這個約束是對的CollectionView,而不是它的父。

+0

謝謝,不幸的是,仍然沒有解決破損的約束。我會發布所有這些。 – Joey 2015-03-07 20:58:46

+1

嘗試添加:'self.collectionViewHeightConstraint.priority = 999',這會降低其優先級以優先於由系統生成的UIView-Encapsulated-Layout-Height約束。您可以將其優先級值設置爲低於1000的值。在iPhone 6模擬器中,CollectionView的高度限制爲510左右,如果您將其高度設置爲大於510,那麼它仍然是510. – gabbler 2015-03-08 02:29:45

+0

感謝您的支持,那確實是問題。 – Joey 2015-03-08 19:56:58

1

在第一組的衝突的約束,這個問題其實是,你的觀點最終比通知中心較短,似乎想讓它。這裏有限制,略微重新排序,這樣他們從從上到下閱讀:

<NSLayoutConstraint:0x6080000998c0 V:|-(10)-[UILabel:0x6000001db300] (Names: '|':UIView:0x60800018f700)> 
<NSLayoutConstraint:0x608000099e60 V:[UILabel:0x6000001db300(25)]> 
<NSLayoutConstraint:0x60800009a2c0 V:[UILabel:0x6000001db300]-(0)-[UICollectionView:0x7ff94b02c200]> 
<NSLayoutConstraint:0x60800009a360 V:[UICollectionView:0x7ff94b02c200(100)]> 
<NSLayoutConstraint:0x60800009a310 UICollectionView:0x7ff94b02c200.bottom == UIView:0x60800018f700.bottom> 

所以,被要求的容器視圖(UIView:0x60800018f700)爲10個+ 25 + 100 == 135點高。這與通知中心施加的這種限制相沖突:

<NSLayoutConstraint:0x60800009a4f0 'UIView-Encapsulated-Layout-Height' V:[UIView:0x60800018f700(667)]> 

它決定了667點的高度。

通知中心希望容器以肯定會比你的約束使它。您可以將集合視圖的底部和其超級視圖的底部之間的約束更改爲不等式 - 超級視圖的底部大於或等於集合視圖的底部。或者,也可以改變約束的集合視圖的高度是一個不等式 - 高度大於或 - 等於-100。

然而,第二種情況是相反的問題。在這種情況下,通知中心在容器視圖上將高度設置爲0。你的約束要求高度不爲零,所以這是一個衝突。您的約束,略微重新排序:

<NSLayoutConstraint:0x6080000998c0 V:|-(10)-[UILabel:0x6000001db300] (Names: '|':UIView:0x60800018f700)> 
<NSLayoutConstraint:0x608000099e60 V:[UILabel:0x6000001db300(25)]> 
<NSLayoutConstraint:0x60800009a2c0 V:[UILabel:0x6000001db300]-(0)-[UICollectionView:0x7ff94b02c200]> 
<NSLayoutConstraint:0x60800009a310 UICollectionView:0x7ff94b02c200.bottom == UIView:0x60800018f700.bottom> 

該容器具有爲10 + 25 +高度集合視圖(隱式> = 0)> = 35點高的。通知中心的約束:

<NSLayoutConstraint:0x60800009a4f0 'UIView-Encapsulated-Layout-Height' V:[UIView:0x60800018f700(0)]> 

我不清楚爲什麼通知中心正在改變這樣的強制高度。這似乎發生在通過忽略集合視圖高度解決第一個衝突之後,因爲它在此日誌中被忽略。

嘗試修復第一個,看看第二個是否消失。如果不這樣做,可以減少集合視圖底部和超級視圖底部之間約束的優先級,比如說900.這仍然幾乎是必需的,所以應該在可能的時候保持佈局,但它不是實際上需要的時間更長 - 它是可選的 - 所以它不會造成不可滿足的約束。

相關問題