简体   繁体   中英

Autoresize UICollectionView height to adjust to its content size

I have a UICollectionView, a button that creates a new cell in collection view. And I want UICollectionView to adjust it's size according to it's content size (when there are one or two cells then UICollectionView is short, if there are a lot of cell UICollectionView is big enough).

I know how to get content size:

collectionView.collectionViewLayout.collectionViewContentSize

But I have no idea where to use this value. I would appreciate if somebody help me to figure out how to make UICollectionView auto adjust it's height.

UPD: I published on GitHub a demo project that describes the problem: https://github.com/avokin/PostViewer

I don't think content size is what you're after. I think you're wanting to adjust the amount of screen real estate consumed by the collection view, right? That's going to require adjustment of the frame. The content size includes the off-screen (scrolling) area as well as the on screen view.

I don't know of anything that would prevent you from just changing the frame size on the fly:

collectionView.frame = CGRectMake (x,y,w,h);
[collectionView reloadData];

If I'm understanding you correctly.

Use a height constraint for the collection view and update its value with the content height when needed. See this answer: https://stackoverflow.com/a/20829728/3414722

Steps to change the UICollectionView frame:

  1. Set the "translatesAutoresizingMaskIntoConstraints" property to YES for the collectioview's superview (If you are using AUTOLAYOUT)

  2. Then update the collectioview's frame as :

     collectionView.frame = CGRectMake (x,y,w,h); [collectionView reloadData]; 

You need to constrain the collection view height to the height of your content:

I'm using SnapKit in the following code.

First constrain the collection view edges to its superview:

private func constrainViews() {
    collectionView?.translatesAutoresizingMaskIntoConstraints = true

    collectionView?.snp.makeConstraints { make in
        make.edges.equalToSuperview()
        heightConstraint = make.height.equalTo(0).constraint
    }
}

Next calculate the height and set the height to the height constraint offset. I'm letting the flow layout do the work, and then calculating the height based on the bottom edge of the last layout attribute:

override func viewDidLayoutSubviews() {
    guard
        let collectionView = collectionView,
        let layout = collectionViewLayout as? UICollectionViewFlowLayout
    else {
        return
    }

    let sectionInset = layout.sectionInset
    let contentInset = collectionView.contentInset

    let indexPath = IndexPath(item: tags.count, section: 0)
    guard let attr = collectionViewLayout.layoutAttributesForItem(at: indexPath) else {
        return
    }

    // Note sectionInset.top is already included in the frame's origin
    let totalHeight = attr.frame.origin.y + attr.frame.size.height
        + contentInset.top + contentInset.bottom
        + sectionInset.bottom

    heightConstraint?.update(offset: totalHeight)
}

Note that in the example, I always have one special tag not included in my items tags count, so the line:

let indexPath = IndexPath(item: tags.count, section: 0)

would need to be something like if items.count > 0 ... let indexPath = IndexPath(item: tags.count - 1, section: 0) in most other code.

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