UICollectionView自定义自定义单元格

Mar*_*nHN 5 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我的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.
    }
}
Run Code Online (Sandbox Code Playgroud)

最后我的观察细胞:

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

hlf*_*ing 4

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

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

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

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