3

Xcode 7.0 ベータ、Swift 2.0、IOS 9 をサポート

コレクション ビューを含むビュー コントローラーがあります。内部には、ヘッダー: Collection Reusable View、コレクション: Collection View Cell、フッター: Collection Reusable View があります。

ヘッダー内には、ログイン、登録、またはログアウトする機能があります。クリックされたボタンに応じて、このヘッダー内のビューが非表示になるかどうかが決まります。最後に、ヘッダー ビュー (コレクションの再利用可能なビュー) のフレームの高さを変更する必要があります。ログインすると、RegisterView と LoginView の両方が非表示になり、大量の空きスペースが残るためです。

ここに私の構造の画像があります:

構造図

コレクションの再利用可能なビューに制約を追加できないことにすぐに気付きました:(

ヘッダー Collection Reusable View のすべての機能は、継承するクラス内にありますUICollectionReusableView。読み取りはできますself.frame.heightが、書き込みはできません。フレームを編集できるようです(フレームはそうではないのに、なぜ高さは読み取り専用なのですか?)。ただし、これは効果がなく、何もself.frame = CGRectZeroしません。

ヘッダーとフッターを初期化するときに、メインのViewController.swift内でこれを実行できることに気付きました(func collectionView, switch on kind -> UICollectionElementKindSectionHeader)が、ボタンのクリック時に変更する必要があるため、これは私が望むものではありません。

とりあえず、RegisterView を上に移動します (コードの一番上の制約を編集します)。

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

パトリックはヘッダーの高さを変更するための正しい答えを出しましたが、質問で言ったように、ヘッダー機能が別のクラスにあったため、実際の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 に答える