编辑框架高度 Collection 可重用视图

edit frame height Collection reusable View

使用 Xcode 7.0 测试版,Swift 2.0,IOS 9 支持

我有一个视图控制器,其中包含一个 Collection 视图。里面是一个header:Collection可复用视图,一个collection:Collection视图单元格和 页脚: Collection 可重用视图。

在header里面,我有登录、注册或注销的功能。 根据单击的按钮,header 中的视图将被隐藏或不隐藏。现在我要做的最后一件事是 re-size header 视图(Collection 可重用视图)的框架高度。因为登录时,RegisterView和LoginView都会被隐藏,会留下大量空白space.

这是我的结构图:

我很快注意到我无法向 Collection 可重用视图添加任何约束:(

header Collection 可重用视图的所有功能都在扩展 UICollectionReusableView 的 class 中。我可以读取 self.frame.height,但无法写入。我似乎可以编辑框架(为什么高度 read-only,而框架不是,苹果?)。然而,这没有任何效果,即使 self.frame = CGRectZero 也没有做任何事情。

我注意到在初始化 header 和页脚 (func collectionView, switch on kind -> UICollectionElementKindSectionHeader) 时,我可以在主 ViewController.swift 中执行此操作,但这不是我想要的,因为它应该更改单击按钮。

现在,我将 RegisterView 向上移动(我编辑了代码中的顶部约束)。

您不能在 collection 视图中直接操作视图的大小。要控制它们的大小,您的 collection 视图的委托应符合 UICollectionViewDelegateFlowLayout,然后您可以 return 通过实现方法 [=] 为该部分中的 header 设置任何您喜欢的大小12=] 在该协议上。如果 header 不可见,只需 return 0.0 作为其高度。一旦您以需要更新此布局的方式更改了视图控制器的状态,请在 collection 视图的布局上调用 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)
        }
    }
}

Patrick 给出了更改 header 高度的正确答案,但是,正如我在问题中所说,我的 header 功能在不同的 class 中,所以我没有真的不知道怎么访问真正的viewControllerclass.

如果你保持简单,你可以只创建一个从故事板到 class 的动作 link,我还有一些操作要做,而不仅仅是响应按钮点击.这就是我所做的:

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)
        }
    }
}