UICollectionView自定义自定义单元格

时间:2014-10-25 22:55:21

标签: ios swift ios8

我的印象是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)
    }
}

然后我的ViewControllerUICollectionViewController的子类,如下所示:

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/

1 个答案:

答案 0 :(得分:4)

您无需覆盖preferredLayoutAttributesFittingAttributes。并且你的覆盖不会调用super,根据文档:

  

此方法的默认实现调整大小值以适应自调整单元格所做的更改。子类可以覆盖此方法并使用它来调整其他布局属性。如果您覆盖此方法并希望调整单元格大小,请先调用super,然后对返回的属性进行自己的修改。

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

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