ios – UICollectionView自定义自定义单元格

我的印象是UICollectionView中的自动调整大小单元在iOS 8中变得非常简单.所以,我可能在这里遗漏了一些东西.

我使用UICollectionViewFlowLayout的子类作为我的布局:

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)
    }
}

然后我的ViewController是UICollectionViewController的子类,如下所示:

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.
    }
}

最后我的观察细胞:

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)
    }
}

单元格的大小设置为布局类中的estimatedItemSize.

我应该在preferredLayoutAttributesFittingAttributes方法中手动计算项目高度吗?

如果是这样,表视图不支持100%自我调整行吗? (http://www.appcoda.com/self-sizing-cells/)

最佳答案
您不需要覆盖preferredLayoutAttributesFittingAttributes.并且你的覆盖不会调用super,根据文档:

The default implementation of this method adjusts the size values to accommodate changes made by a self-sizing cell. Subclasses can override this method and use it to adjust other layout attributes too. If you override this method and want the cell size adjustments, call super first and make your own modifications to the returned attributes.

所以你得到的警告是合法的.它告诉你你的细胞不能比你的集合视图宽.这可能是因为当您设置estimatedItemSize时,您没有考虑项目间间距(默认情况下为> 0).尝试设置更小的尺寸.它应该工作.

如果您正在尝试仅尝试自动调整一个尺寸(即始终保持整个宽度),那么请不要打扰.它不起作用,因为estimatedItemSize意味着两个维度都可以调整大小.

转载注明原文:ios – UICollectionView自定义自定义单元格 - 代码日志