2015-03-02 4 views
1

Виджет моего Notification Center должен иметь динамическую высоту на основе содержащегося в нем содержимого. У меня простой интерфейс - один 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

Вы показываете, какое ограничение система решает сломать, но это в основном произвольно. Вам нужно показать весь список ограничений, которые конфликтуют. –

+0

@KenThomases Спасибо, обновлено – Joey

ответ

0

Изменение self.view.addConstraint(self.collectionViewHeightConstraint) к collectionView.addConstraint(self.collectionViewHeightConstraint), потому что это ограничение для CollectionView, а не его SuperView.

+0

Спасибо, к сожалению, что до сих пор не устранены сломанные ограничения. Я опубликую все это. – Joey

+1

Попытайтесь добавить это: 'self.collectionViewHeightConstraint.priority = 999', это снижает приоритет, чтобы придать приоритет' UIView-Encapsulated-Layout-Height', который генерируется системой. Вы можете установить его значение приоритета на значение ниже 1000. Лимит высоты CollectionView составляет около 510 в симуляторе iPhone 6, если вы установите его высоту больше, чем это, но все равно 510. – gabbler

+0

Спасибо за это, это действительно было частью проблема. – Joey

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. Это все еще требуется, и поэтому вы должны сохранять свой макет, когда это возможно, но это не так дольше фактически требуется - это необязательно - поэтому он не может способствовать неудовлетворительным ограничениям.

Смежные вопросы