2016-10-19 13 views
16

これは、iOS 10(まだ11の問題)でUICollectionViewFlowLayoutで見つかった興味深い問題で、estimatedItemSizeにはUICollectionViewFlowLayoutAutomaticSizeを使用しています。iOS 10/11 UICollectionViewFlowLayoutAutomaticSizeを使用したUICollectionViewFlowLayoutフッタ補足ビューの整列がずれて

我々は下少数の細胞浮いフッター補助的なビューでestimatedItemSize結果のUICollectionViewFlowLayoutAutomaticSizeを使用していることがわかりました。(レッド/ピンクがヘッダーで、緑はフッタです。)

UICollectionViewFlowLayoutAutomaticSize problem enter image description here

ここで

は、サンプルアプリのVCコードです:

import UIKit 

class ViewController: UIViewController { 

    // MARK: Properties 

    let texts: [String] = [ 
     "This is some text", 
     "This is some more text", 
     "This is even more text" 
    ] 

    // MARK: Outlets 

    @IBOutlet var collectionView: UICollectionView! { 
     didSet { 
      self.collectionView.backgroundColor = .orange 
     } 
    } 

    // MARK: Lifecycle 

    override func viewDidLoad() { 

     super.viewDidLoad() 

     // Layout 
     let layout = UICollectionViewFlowLayout() 
     layout.scrollDirection = .vertical 
     if #available(iOS 10.0, *) { 
      layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize 
     } else { 
      layout.estimatedItemSize = CGSize(width: self.collectionView.bounds.width, height: 50) 
     } 
     self.collectionView.collectionViewLayout = layout 

     // Register Cells 
     self.collectionView.register(UINib(nibName: "TextCell", bundle: nil), forCellWithReuseIdentifier: String(describing: TextCell.self)) 
     self.collectionView.register(UINib(nibName: "SectionHeader", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: String(describing: SectionHeader.self)) 
     self.collectionView.register(UINib(nibName: "SectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: String(describing: SectionFooter.self)) 

     self.collectionView.reloadData() 
    } 
} 

// MARK: - UICollectionViewDelegateFlowLayout Methods 

extension ViewController: UICollectionViewDelegateFlowLayout { 

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

     return CGSize(width: self.collectionView.bounds.width, height: 90) 
    } 

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

     return CGSize(width: self.collectionView.bounds.width, height: 90) 
    } 
} 

// MARK: - UICollectionViewDataSource Methods 

extension ViewController: UICollectionViewDataSource { 

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

     return self.texts.count 
    } 

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

    public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 

     let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: TextCell.self), for: indexPath) 

     if let textCell = cell as? TextCell { 

      let text = self.texts[indexPath.row] 
      textCell.configure(text: text) 
     } 

     return cell 
    } 

    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { 

     switch kind { 
     case UICollectionElementKindSectionHeader: 

      return collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: String(describing: SectionHeader.self), for: indexPath) 

     case UICollectionElementKindSectionFooter: 

      return collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: String(describing: SectionFooter.self), for: indexPath) 

     default: 
      return UICollectionReusableView() 
     } 
    } 
} 

// MARK: - UICollectionViewDelegate Methods 

extension ViewController: UICollectionViewDelegate { 

} 

は、誰もがUIColleを取得するために管理しています補足的なヘッダービューとフッタービューでiOS 10で動作するctionViewFlowLayoutAutomaticSize? estimatedItemSizeにサイズを追加すると動作するように見えますが、新しいiOS 10の機能を使用する際にバグがあるか、誤って使用しているかどうかを知りたいと思います。

アップルに提出されたバグはIDを持っています

UPDATE:これはまだのように見える:これはまだ10.3 Beta 1の

UPDATE 2上の問題のように見えますiOS 11ベータ版の問題

+0

estimatedItemSize afaikを指定する必要があります。オプションではありません – Lefteris

+0

設定されていますが、iOS 10以前とはちょっと違います。 – dlbuckley

+0

解決方法を見つけましたか? –

答えて

0

同じ問題が発生しました。 UICollectionViewFlowLayoutAutomaticSizeは補助ビューでは機能しません。サイズを明示的に指定するには、UICollectionViewDelegateFlowLayoutを使用します。サイズを計算してデリゲートを自動サイズ計算として使用する方が時間がかかります。

referenceSizeForHeaderInSectionreferenceSizeForFooterInSectionを使用して、ヘッダーとフッターのサイズを明示的に指定します。

+0

入力いただきありがとうございます。私が投稿したコードを見ても、 'referenceSizeForHeaderInSection'と' referenceSizeForFooterInSection'デリゲートメソッドを使って高さを90ptに設定しています。それとも他のことを言いたいのですか? – dlbuckley

+0

コードは問題ありません。この部分を削除し、計算を使用して細胞のサイズを与えてみてください。 '#available IF(IOSの10.0、*){ layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize }他{ layout.estimatedItemSize = CGSize(幅:self.collectionView.bounds.width、高さ:50) }' –

+0

それが動作するかどうか私は 'UICollectionViewFlowLayoutAutomaticSize'を使用しませんが、質問の全体的なポイントは' UICollectionViewFlowLayoutAutomaticSize'の仕組みを理解することでした。私たちのソリューションはあなたの提案と同じように、最終的には自動サイジングを動かしましたが、将来的には自動サイジングを使用するのもいいでしょう。 – dlbuckley

14

UICollectionViewFlowLayoutは、セルの自動レイアウトを非常によくサポートしています。BUT補助ビューではサポートしていません。自動レイアウトコードがセルのフレームを更新するたびに、ヘッダーとフッターで何もしません。ヘッダーやフッターを無効にする必要があることをレイアウトに伝える必要があります。そして、これには方法があります!

UICollectionViewLayoutfunc invalidationContext(forPreferredLayoutAttributes: UICollectionViewLayoutAttributes, withOriginalAttributes: UICollectionViewLayoutAttributes)を無効にして、補足表示の無効化を実行する必要があります。

例:

override open func invalidationContext(forPreferredLayoutAttributes preferred: UICollectionViewLayoutAttributes, 
     withOriginalAttributes original: UICollectionViewLayoutAttributes) 
       -> UICollectionViewLayoutInvalidationContext { 
    let context: UICollectionViewLayoutInvalidationContext = super.invalidationContext(
      forPreferredLayoutAttributes: preferred, 
      withOriginalAttributes: original 
    ) 

    let indexPath = preferred.indexPath 

    if indexPath.item == 0 { 
     context.invalidateSupplementaryElements(ofKind: UICollectionElementKindSectionHeader, at: [indexPath]) 
    } 

    return context 
} 

Iセクションの最初のセルが無効にされた場合、ヘッダ補助ビューを無効にするUICollectionViewFlowLayoutによって提供される無効化コンテキストを使用している上記の例では。フッターの無効化にもこのメソッドを使用できます。

+2

これは私の問題を解決しました。突然、私のヘッダービューが正しく配置されました。 – MurderDev

+0

私の主張では、 'context.invalidateItems(at:)'を呼び出すことによって 'if'スコープ内でセル自体も無効にする必要があります。 – billibala

関連する問題