简体   繁体   中英

Collectionview dynamic width not worked Swift

I have one collectionView inside Table view, it works perfectly but the issue is that collection view cell width not worked perfectly on initial stage but worked once scrolls it.

检查这个

You can check here that in the first section, it shows full name but in other section, it truncates tail and that works after scrolls.

Here is the code that matters

class SubjectsViewFlowLayout: UICollectionViewFlowLayout {

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    let attributesForElementsInRect = super.layoutAttributesForElements(in: rect)
    var newAttributesForElementsInRect = [UICollectionViewLayoutAttributes]()
    // use a value to keep track of left margin
    var leftMargin: CGFloat = 0.0
    for attributes in attributesForElementsInRect! {
        let refAttributes = attributes
        // assign value if next row
        if (refAttributes.frame.origin.x == self.sectionInset.left) {
            leftMargin = self.sectionInset.left
        } else {
            // set x position of attributes to current margin
            var newLeftAlignedFrame = refAttributes.frame
            newLeftAlignedFrame.origin.x = leftMargin
            if newLeftAlignedFrame.origin.x + newLeftAlignedFrame.size.width > (self.collectionView?.bounds.size.width)! {
                leftMargin = 0.0
                newLeftAlignedFrame.origin.x = 0.0
                if (newAttributesForElementsInRect.last?.frame.origin.y == newLeftAlignedFrame.origin.y){
                    newLeftAlignedFrame.origin.y = newLeftAlignedFrame.origin.y + newLeftAlignedFrame.height + minimumLineSpacing
                }
            }
            refAttributes.frame = newLeftAlignedFrame
        }
        // calculate new value for current margin
        leftMargin += refAttributes.frame.size.width + 10
        newAttributesForElementsInRect.append(refAttributes)
    }
    return newAttributesForElementsInRect
}
}

class DynamicCollectionView: UICollectionView {
override func layoutSubviews() {
    super.layoutSubviews()
    if !__CGSizeEqualToSize(bounds.size, self.intrinsicContentSize) {
        self.invalidateIntrinsicContentSize()
        if self.superview?.superview?.superview is UITableView {
            (self.superview?.superview?.superview as! UITableView).beginUpdates()
            (self.superview?.superview?.superview as! UITableView).endUpdates()
        }
    }
}

override var intrinsicContentSize: CGSize {
    return collectionViewLayout.collectionViewContentSize
}
}

class TagTableCell: UITableViewCell {
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var flowLayout: SubjectsViewFlowLayout!

override func awakeFromNib() {
    super.awakeFromNib()
    collectionView.register(UINib(nibName: "TagCollectionCell", bundle: nil), forCellWithReuseIdentifier: "TagCollectionCell")
}

func setupCell() {
    let flowLayout = collectionView.collectionViewLayout as? SubjectsViewFlowLayout
    flowLayout?.estimatedItemSize = .init(width: 100, height: 45)

    DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
        self.collectionView.reloadData()
    }
}

func setCollectionViewDataSourceDelegate<D: UICollectionViewDataSource & UICollectionViewDelegate>(_ dataSourceDelegate: D, forRow row: Int) {
    setupCell()
    collectionView.delegate = dataSourceDelegate
    collectionView.dataSource = dataSourceDelegate
    collectionView.tag = row + 1
    collectionView.layoutIfNeeded()
}
}

You just need to call datasource and datadelegate in async method while adding the UICollectionView in tableview cell

    DispatchQueue.main.async {
        self.collectionView.delegate = dataSourceDelegate
        self.collectionView.dataSource = dataSourceDelegate
    }

You can modify your cell size just by adding this function, change your desired width and height for each cell. Here is an example to make the cell's width half of the collection view's.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let cellWidth = collectionView.layer.bounds.width / 2
        let cellHeight : CGFloat = 150
        return CGSize(width: cellWidth, height: cellHeight)
    }

You should implement this Protocol to your class:

UICollectionViewDelegateFlowLayout

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM