Swift - 基于内容的UICollectionView高度

时间:2017-08-23 12:28:59

标签: ios swift uicollectionview nib

所以我一直在尝试使用自定义FlowLayout创建一个集合视图,以根据它包含的UICollectionViewCells调整自己的高度。我一直在网上搜索很多,我找到的所有解决方案导致在运行时引发不同的异常。

要知道的是,我的collectionview位于tableview单元格内。当tableview单元格的内容需要更多/更少的空间时,它们的高度会相应变化,但是它们包含的集合视图不会....

大多数情况下,有问题的集合视图有一两个项目,它们的宽度使它们适合单行。但有时,物品太宽,因此需要相互包裹。

当发生这种情况时,collectionview的高度应该展开以显示两行项目,但这不会发生。

一些信息:

Nib文件 How the collectionview is implemented

Nib文件的awakeFromNib() The tableview cell's awakeFromNib

class BaseOnboardingTableViewCell: UITableViewCell {

@IBOutlet weak var watsonIndicator: UIView!
@IBOutlet weak var cellTextLabel: UILabel!
@IBOutlet weak var customContentViewContainer: UIView!
@IBOutlet weak var actionButtonsCollection: UICollectionView!

@IBOutlet var customContentViewContainerHeightConstraint: NSLayoutConstraint!
@IBOutlet var actionButtonsCollectionHeightConstraint: NSLayoutConstraint!

@IBOutlet var customContentDistanceFromCellTextLabelConstraint: NSLayoutConstraint!
@IBOutlet var actionButtonsCollectionDistanceFromCustomContentConstraint: NSLayoutConstraint!

/// Keeps track wether the cell has animated for its intro or not
var hasAnimated: Bool = false

/// Receiver for interaction with chat actions
var chatActionDelegate: OnboardingChatActionDelegate?

/// Dictates what the cell should contain and display
var onboardingStep: OnboardingStep! {
    didSet {
        if onboardingStep.text() != nil {
            cellTextLabel.text = onboardingStep.text()!
        } else {
            hideText()
        }

        if onboardingStep.customContent != nil {
            loadCustomContent()
        } else {
            hideCustomContent()
        }

        if onboardingStep.chatActions == nil {
            hideActionButtonsCollection()
        } else {
            actionButtonsCollection.collectionViewLayout.invalidateLayout()
            actionButtonsCollection.reloadData()
            actionButtonsCollectionHeightConstraint.constant = actionButtonsCollection.contentSize.height
        }
    }
}


/// Prepares the cell before setting its OnboardingStep
override func awakeFromNib() {
    super.awakeFromNib()

    self.translatesAutoresizingMaskIntoConstraints = true

    let collectionController = OnboardingChatActionCollectionViewController()
    collectionController.attach(toCollection: actionButtonsCollection)
    collectionController.onboardingCellDelegate = self

    actionButtonsCollection.sizeToFit()
    watsonIndicator.layer.cornerRadius = watsonIndicator.frame.width/2
    makeAllTransparent()
}

CollectionView的控制器 The collectionview's controller

class OnboardingChatActionCollectionViewController: UICollectionViewFlowLayout, UICollectionViewDataSource, UICollectionViewDelegate {

var onboardingCellDelegate: BaseOnboardingTableViewCell?


/// This will link a UICollectionView to this controller
func attach(toCollection collection: UICollectionView) {
    collection.delegate = self
    collection.dataSource = self
    collection.collectionViewLayout = self

    collection.contentInset.left = 0
    collection.contentInset.right = 0

    collection.backgroundColor = UIColor.clear

    self.estimatedItemSize = CGSize(width: 50, height: 29)


    collection.register(UINib(nibName: "ChatActionButton", bundle: nil), forCellWithReuseIdentifier: "ChatActionButtonCell")
}


/// Renders buttons inactive and greys them out (based on user selection) after an action was tapped
fileprivate func greyOutButtons(selectedCell: OnboardingChatActionCollectionViewCell) {
    DispatchQueue.main.async {

        let cells = self.collectionView!.visibleCells as! [OnboardingChatActionCollectionViewCell]

        for cell in cells {
            if cell == selectedCell {
                cell.background.backgroundColor = UIColor(colorLiteralRed: 52/255, green: 51/255, blue: 52/255, alpha: 1)
            } else {
                cell.background.backgroundColor = UIColor.aqua10
                cell.actionButton.setTitleColor(UIColor.gunmetal, for: .normal)
            }

            cell.actionButton.isEnabled = false
        }
    }
}


/// Wrapping buttons on a new row if they're too large
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    let attributes = super.layoutAttributesForElements(in: rect)

    var leftMargin = sectionInset.left
    var maxY: CGFloat = -1.0
    attributes?.forEach { layoutAttribute in
        if layoutAttribute.frame.origin.y >= maxY {
            leftMargin = sectionInset.left
        }

        layoutAttribute.frame.origin.x = leftMargin

        leftMargin += layoutAttribute.frame.width + minimumInteritemSpacing
        maxY = max(layoutAttribute.frame.maxY , maxY)
    }

    return attributes
}


func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return onboardingCellDelegate?.onboardingStep.chatActions?.count ?? 0
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let chatActionCell = self.collectionView!.dequeueReusableCell(withReuseIdentifier: "ChatActionButtonCell", for: indexPath) as! OnboardingChatActionCollectionViewCell

    chatActionCell.chatAction = onboardingCellDelegate!.onboardingStep.chatActions![indexPath.row]

    chatActionCell.background.layer.cornerRadius = chatActionCell.background.frame.height / 2
    chatActionCell.sizeToFit()

    chatActionCell.collectionControllerDelegate = self

    return chatActionCell
}

0 个答案:

没有答案