0

I am trying to make a collectionView header become hidden when a button is tapped but I cant seem to access this property from inside of the IBAction function.

button function

    var buttonPressed:Bool = true
    @IBAction func changeView(_ sender: Any) {
        if buttonPressed{
        UIView.animate(withDuration: 0.05){

            self.buttonPressed = !self.buttonPressed
            print("Ive been expanded")
        }
        }
        else{
            UIView.animate(withDuration: 0.05){
                self.buttonPressed = !self.buttonPressed
            }
        }
    }   
}

Code in its entirety

import UIKit

class ViewController: UIViewController,UICollectionViewDataSource,UICollectionViewDelegate {

    @IBOutlet weak var animateCollectionView: UICollectionView!



    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        animateCollectionView.dataSource = self
        animateCollectionView.delegate = self
        animateCollectionView.backgroundColor = UIColor.blue
        animateCollectionView.frame = CGRect(x: 0, y: 100, width: 600, height: 1000)
        let layout = animateCollectionView.collectionViewLayout as? UICollectionViewFlowLayout
        layout?.sectionHeadersPinToVisibleBounds = true
         self.view.sendSubview(toBack: self.animateCollectionView)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

        return 200
    }

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = self.animateCollectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! customCell
        cell.cellLabel.text = "\(indexPath.item)"
        cell.backgroundColor = UIColor.orange
        return cell


    }

    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        // returning the search bar for header
        let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "headerCell", for: indexPath) as! customHeader

        header.backgroundColor = UIColor.purple

        return header
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        // if section is above search bar we need to make its height 0
        if section == 0 {
            return CGSize(width: 0, height: 0)
        }
        // for section header i.e. actual search bar
        return CGSize(width: animateCollectionView.frame.width, height: 50)
    }


    var buttonPressed:Bool = true
    @IBAction func changeView(_ sender: Any) {
        if buttonPressed{
        UIView.animate(withDuration: 0.05){
      self.buttonPressed = !self.buttonPressed
            print("Ive been expanded")
        }
        }
        else{
            UIView.animate(withDuration: 0.05){

            }
        }
    }




}

class customCell :UICollectionViewCell{
    @IBOutlet weak var cellLabel: UILabel!
}

class customHeader: UICollectionReusableView{

}

1 Answers1

1

As @SPatel mentioned, set the size to zero.

Then set up a delegate method from the cell to the VC so that the VC knows to invalidate layouts.

For instance:

Cell Class

protocol HideHeaderViewDelegate {
    func hideHeaderView(hide: Bool)
}

class HeaderView: UICollectionReusableView {

    var delegate: HideHeaderViewDelegate?

    @IBOutlet weak var hideButton: UIButton!

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    @IBAction func hideButtonAction(_ sender: Any) {
        self.frame.size = CGSize.zero
        guard let delegate = delegate else { return }
        delegate.hideHeaderView(hide: true)
    }
}

View Controller

extension ViewController: HideHeaderView {
    func hideHeaderView(hide: Bool) {
        if hide == true {
            print(hide)
            // invalidate your layout here
        }
    }
}

Don't forget to set the delegate

func collectionView(_ collectionView: UICollectionView,
                        viewForSupplementaryElementOfKind kind: String,
                        at indexPath: IndexPath) -> UICollectionReusableView {
        let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader,
                                                                         withReuseIdentifier: "headerView", for: indexPath) as! HeaderView
        headerView.delegate = self

    return headerView
    }
David Henry
  • 1,972
  • 20
  • 43
  • Thank you so much for your response it is very helpful. I am curious if I wanted to trigger the header hiding by an event occurring within the viewController lets say by a button in the viewController or the collectionView scrolling would that be possible? How would you set up the delegate? – TheRedCamaro3.0 3.0 Jul 10 '18 at 05:17
  • @TheRedCamaro3.03.0 UICollectionView is a Subclass of ScrollView. You'll need this delegate: UIScrollViewDelegate, then you can use its methods. For more information on this, I'd search through SOF or post a separate question. :) – David Henry Jul 10 '18 at 05:41
  • What is the code inside the hideHeaderView function to actually hide the header view? – paprika Aug 29 '22 at 13:14