UICollectionView Self-Assessment Custom Cell

I got the impression that automatic cell calibration in UICollectionView became very easy in iOS 8. So, I probably missed something.

I use a subclass of UICollectionViewFlowLayout as my layout:

 class BuildCollectionViewFlowLayout: UICollectionViewFlowLayout { required init(coder: NSCoder) { super.init(coder: coder) self.minimumLineSpacing = 1 self.sectionInset.top = 20 self.estimatedItemSize = CGSize(width: UIScreen.mainScreen().bounds.width, height: 90) } } 

Then my ViewController , which is a subclass of UICollectionViewController , looks like this:

 class ViewController: UICollectionViewController { let CellIdentifier = "CellIdentifier" let apiClient: APIClient() var builds:Array<JSON>? = [] override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. self.collectionView.registerClass(BuildProjectStatusCollectionViewCell.self, forCellWithReuseIdentifier: CellIdentifier) self.apiClient.getProjects({ (projects, error) -> Void in if (error == nil) { dispatch_async(dispatch_get_main_queue(), { self.builds = projects self.collectionView.reloadData() }) } else { } }) } override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return self.builds!.count; } override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { var cell:BuildProjectStatusCollectionViewCell = self.collectionView.dequeueReusableCellWithReuseIdentifier(CellIdentifier, forIndexPath: indexPath) as BuildProjectStatusCollectionViewCell; cell.setup(self.builds?[indexPath.row]) return cell; } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } } 

And finally, my view cell:

 class BuildProjectStatusCollectionViewCell : UICollectionViewCell { var projectNameLabel: UILabel! var lastCommitMessageLabel: UILabel! override init(frame: CGRect) { super.init(frame: frame) self.initialize() } required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) self.initialize() } override func awakeFromNib() { self.initialize() } func initialize() { self.contentView.frame = self.bounds; self.contentView.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight self.projectNameLabel = UILabel(forAutoLayout: ()) self.lastCommitMessageLabel = UILabel(forAutoLayout: ()) self.lastCommitMessageLabel.autoresizingMask = UIViewAutoresizing.FlexibleHeight self.lastCommitMessageLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping self.lastCommitMessageLabel.numberOfLines = 0 self.contentView.addSubview(self.projectNameLabel) self.contentView.addSubview(self.lastCommitMessageLabel) setNeedsUpdateConstraints() } func setup(project:JSON!) -> Void { self.projectNameLabel!.text = project["name"].stringValue let builds: Array<JSON> = project["builds"].arrayValue! if builds.count == 1 { if builds[0]["status"].stringValue == "success" { self.backgroundColor = UIColor(red: 68/255, green: 175/255, blue: 105/255, alpha: 1.0) } else { self.backgroundColor = UIColor(red: 254/255, green: 57/255, blue: 48/255, alpha: 1.0) } self.lastCommitMessageLabel!.text = builds[0]["message"].stringValue } } override func preferredLayoutAttributesFittingAttributes(layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes! { let attr: UICollectionViewLayoutAttributes = layoutAttributes.copy() as UICollectionViewLayoutAttributes // Without this, it crashes. AutoLayout constraints playing around. Error: the item width must be less than the width of the UICollectionView minus the section insets left and right values. return attr; } override func updateConstraints() { super.updateConstraints() self.projectNameLabel.autoPinEdgesToSuperviewEdgesWithInsets(UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5), excludingEdge: ALEdge.Bottom) self.lastCommitMessageLabel.autoPinEdge(ALEdge.Top, toEdge: ALEdge.Bottom, ofView: self.projectNameLabel, withOffset: 10) self.lastCommitMessageLabel.autoPinEdgeToSuperviewEdge(ALEdge.Leading, withInset: 5) self.lastCommitMessageLabel.autoPinEdgeToSuperviewEdge(ALEdge.Trailing, withInset: 25) } } 

Cells get the size specified as estimatedItemSize in the layout class.

Should I do a manual calculation of the element height in the preferredLayoutAttributesFittingAttributes method?

If so, aren't the tables showing the tables 100% of their own sizes? ( http://www.appcoda.com/self-sizing-cells/ )

+5
source share
1 answer

You do not need to override preferredLayoutAttributesFittingAttributes . And your redefinition does not call super, which according to the docs:

The default implementation of this method adjusts the size values ​​to account for changes made by the self-sized cell. Subclasses can override this method and use it to set other layout attributes. If you override this method and want to resize the cell, first call super and make your own changes to the returned attributes.

Therefore, the warning you receive is legal. This suggests that your cell cannot be wider than your collection. And this is probably because you did not consider the spacing between the elements (which by default is> 0) when you set the estimatedItemSize . Try setting a much smaller size. It should work.

And if what you are doing is trying to automate only one dimension (i.e. always keep the full width), then don't worry. It will not work, since estimatedItemSize designed to resize both sizes.

+4
source

Source: https://habr.com/ru/post/1205521/


All Articles