3

using Xcode 7.0 beta, Swift 2.0, IOS 9 supported

I have a View Controller, which contains a Collection View. Inside is a header: Collection Reusable View, a collection: Collection View Cell and a footer: Collection Reusable View.

Inside the header, I have the functionality to login, register or logout. Depending on what button is clicked, Views inside this header will be hidden or not. Now the last thing I have to do is re-size the frame height of the header view (Collection Reusable View). Because when logged in, both RegisterView and LoginView will be hidden which will leave a large amount of empty space.

here is an image of my structure:

structure views

I quickly noticed that I'm unable to add any constraints to the Collection Reusable View :(

All the functionality for the header Collection Reusable View is inside a class that extends UICollectionReusableView. I'm able to read self.frame.height, but I cannot write to it. I seem to be able to edit the frame (why is height read-only, while frame is not, apple?). This however has no effect, even self.frame = CGRectZero doesn't do anything.

I noticed I can do this inside the main ViewController.swift, when initializing the header and footer (func collectionView, switch on kind -> UICollectionElementKindSectionHeader), but this is not what I want as it should change on button click.

For now, I move the RegisterView up (I edit the top constraint in the code).

4

2 回答 2

5

您不能直接在集合视图中操作视图的大小。要控制它们的大小,您的集合视图的委托应符合,然后您可以通过在该协议上UICollectionViewDelegateFlowLayout实现该方法为该部分中的标头返回您喜欢的任何大小。collectionView(_:layout:referenceSizeForHeaderInSection:)如果标题不可见,只需返回0.0它的高度。一旦您以需要更新此布局的方式更改了视图控制器的状态,请调用invalidateLayout()集合视图的布局以触发要调用的委托上的这些布局方法。

class MyCollectionViewController : UICollectionViewController, UICollectionViewDelegateFlowLayout {

    var shouldHideHeader: Bool = false {
        didSet {
            self.collectionView?.collectionViewLayout.invalidateLayout()
        }
    }

    let defaultHeaderSize: CGFloat = 100.0
    let loginHeaderSectionIndex: Int = 0

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {

        if self.shouldHideHeader && section == self.loginHeaderSectionIndex {
            return CGSize(width: collectionView.bounds.width, height: 0.0 )
        }
        else {
            return CGSize(width: collectionView.bounds.width, height: self.defaultHeaderSize)
        }
    }
}
于 2015-07-10T17:29:36.247 回答
-1

Patrick 给出了更改标题高度的正确答案,但是,正如我在问题中所说,我的标题功能在不同的类中,所以我真的不知道如何访问真正的 viewController 类。

如果您保持简单,您可以创建一个从情节提要到该类的操作链接,我还有一些操作要做,而不仅仅是响应按钮单击。这就是我所做的:

class MyViewController : UIViewController, UICollectionDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout{  

    var headerHeight: CGFloat = 100.0
    var shouldChangeHeader : Bool? = false
    let loginHeaderSectionIndex: Int = 0

   func setHeaderHeight(height : CGFloat!)
   {
       headerHeight = height
       shouldChangeHeader = true
       self.collectionView.collectionViewLayout.invalidateLayout()
   }

    func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
        switch kind
        {
        case UICollectionElementKindSectionHeader:
            let headerView = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "loginHeader", forIndexPath: indexPath) as! LoginHeaderView
           //you should already have this method, LoginHeaderView is the class with all the functionality for the header, we register a callback.
            headerView.registerHeightChangeCallback(setHeaderHeight)
            return headerView
       }
}
    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        //here we actually change the height, best is to include a if-condition, so it won't change on loading unless you especially call it.
        if self.shouldChangeHeader && self.loginHeaderSectionIndex == section {
            shouldChangeHeader = false
            return CGSize(width: collectionView.bounds.width, height: headerHeight )
        }
        else {
            //do nothing, keep as it is now.
            return CGSize(width: collectionView.bounds.width, height: collectionView.bounds.height) /
        }
    }
}

class LoginHeaderView : UICollectionReusableView {

    var heightCallback : ((height : CGFloat!)-> Void)?
    func registerHeightChangeCallback(callback :((height : CGFloat!)-> Void)?)
    {
        heightCallback = callback
    }
    @IBAction func buttonClicked( sender: AnyObject? ) { //or from any other method...

        if(heightCallback != nil)
        {
            heightCallback!(height: 200)
        }
    }
}
于 2015-07-10T21:54:50.580 回答