Tobias Tobias - 10 days ago 15
iOS Question

Expandable UICollectionViewCell

I'm trying to program an expandable UICollectionViewCell.
If the user presses the topbutton, the cell should expand to a different height and reveal the underlying content.

My first implementation features a custom UICollectionViewCell, which can be expanded by clicking the topbutton, but the collectionview does not expand too. Atm. the cell is the last one in the collectionview and just by swiping down enough, you can see the expanded content. If you stop touching, the scrollview jumps up and nothing of the expanded cell could be seen.

Here's my code:

import Foundation
import UIKit

class ExpandableCell: UICollectionViewCell {

@IBOutlet weak var topButton: IconButton!

public var expanded : Bool = false

private var expandedHeight : CGFloat = 200

private var notExpandedHeight : CGFloat = 50

@IBAction func topButtonTouched(_ sender: AnyObject) {
if (expanded == true) {
self.deExpand()
} else {
self.expand()
}
}

public func expand() {
UIView.animate(withDuration: 0.8, delay: 0.0, usingSpringWithDamping: 0.9, initialSpringVelocity: 0.9, options: UIViewAnimationOptions.curveEaseInOut, animations: {
self.frame = CGRect(x: self.frame.origin.x, y: self.frame.origin.y, width: self.frame.size.width, height: self.expandedHeight)
}, completion: { success in
self.expanded = true
})
}

public func deExpand() {
UIView.animate(withDuration: 0.8, delay: 0.0, usingSpringWithDamping: 0.9, initialSpringVelocity: 0.9, options: UIViewAnimationOptions.curveEaseInOut, animations: {
self.frame = CGRect(x: self.frame.origin.x, y: self.frame.origin.y, width: self.frame.size.width, height: self.notExpandedHeight)
}, completion: { success in
self.expanded = false
})
}
}


I also have problems implementing the following method correctly, because I haven't got a direct reference to the cell:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize


Basicly everything should be animated.

The screenshot shows an expanded and not expanded cell. Hope that helps!

opened and closed cell

Thanks!

Answer

Don't change the cell frame directly. Implement func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize and handle heights there.

Lets say you have one cell in your collectionView and a top button above it:

let expanded = false

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize{
if expanded{
   // what is the size of the expanded cell?
   return collectionView.frame.size 
}else{
    // what is the size of the collapsed cell?
   return CGSizeZero
}
}

@IBAction func didTouchUpInsideTopButton(sender: AnyObject){
    // top button tap handler
    self.expanded = !self.expanded
    // this call will reload the cell and make it redraw (animated) Since the expanded flag changed, the sizeForItemAt call above will return a different size and animate the size change
    self.collectionView.reloadItemsAtIndexPaths([NSIndexPath(forRow: 0, inSection: 0)])
}