2017-11-21 3 views

答えて

2

コレクションビューレイアウトはcustom layout classを作成することによって達成することができます。

論:

は、基本的には、コレクションビューが必要なレイアウト情報を求めて、全体的なレイアウトプロセスを管理するためのカスタムレイアウトオブジェクトを直接動作します。

レイアウトプロセス中、コレクションビューはレイアウトオブジェクトの特定のメソッドを呼び出します。これらのメソッドは、アイテムの位置を計算し、コレクションビューに必要な主要情報を提供する機会を提供します。

  1. prepare()

    次のメソッドは、常にレイアウトプロセス中の順序で呼び出されたレイアウト情報

  2. collectionViewContentSizeを提供するために必要なアップフロントの計算を実行します。ベースのコンテンツ領域全体の全体のサイズを返します。
  3. layoutAttributesForElements(in:):指定された四角形内にあるセルとビューの属性を返します。

実践:

  1. 前提条件:さんはUICollectionViewLayout サブクラスを作成してみましょう、私たちは場所にCollectionビューを持っていると データソースおよび代表者で構成されたと仮定。私はそれをHiveLayoutと命名した。ストーリーボードの collectionViewにも割り当てました。また、

    // Properties for configuring the layout: the number of columns and the cell padding. 
    fileprivate var numberOfColumns = 3 
    fileprivate var cellPadding: CGFloat = 10 
    
    // Cache the calculated attributes. When you call prepare(), you’ll calculate the attributes for all items and add them to the cache. You can be efficient and query the cache instead of recalculating them every time. 
    fileprivate var cache = [UICollectionViewLayoutAttributes]() 
    
    // Properties to store the content size. 
    fileprivate var contentHeight: CGFloat = 0 
    fileprivate var contentWidth: CGFloat { 
        guard let collectionView = collectionView else { 
         return 0 
        } 
        let insets = collectionView.contentInset 
        return collectionView.bounds.width - (insets.left + insets.right) 
    } 
    
  2. prepare()プロセスにおいて有用であろういくつかの変数が必要になります。私たちは、実際に細胞

    override func prepare() { 
        // If cache is empty and the collection view exists – calculate the layout attributes 
        guard cache.isEmpty == true, let collectionView = collectionView else { 
         return 
        } 
    
        // xOffset: array with the x-coordinate for every column based on the column widths 
        // yOffset: array with the y-position for every column, Using odd-even logic to push the even cell upwards and odd cells down. 
        let columnWidth = contentWidth/CGFloat(numberOfColumns) 
        var xOffset = [CGFloat]() 
        for column in 0 ..< numberOfColumns { 
         xOffset.append(CGFloat(column) * columnWidth) 
        } 
        var column = 0 
    
        var yOffset = [CGFloat]() 
        for i in 0..<numberOfColumns { 
         yOffset.append((i % 2 == 0) ? (columnWidth/2) : 0) 
        } 
    
        for item in 0 ..< collectionView.numberOfItems(inSection: 0) { 
    
         let indexPath = IndexPath(item: item, section: 0) 
    
         // Calculate insetFrame that can be set to the attribute 
         let cellHeight = columnWidth - (cellPadding * 2) 
         let height = cellPadding * 2 + cellHeight 
         let frame = CGRect(x: xOffset[column], y: yOffset[column], width: columnWidth, height: height) 
         let insetFrame = frame.insetBy(dx: cellPadding, dy: cellPadding) 
    
         // Create an instance of UICollectionViewLayoutAttribute, sets its frame using insetFrame and appends the attributes to cache. 
         let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath) 
         attributes.frame = insetFrame 
         cache.append(attributes) 
    
         // Update the contentHeight to account for the frame of the newly calculated item. It then advances the yOffset for the current column based on the frame 
         contentHeight = max(contentHeight, frame.maxY) 
         yOffset[column] = yOffset[column] + height 
    
         column = column < (numberOfColumns - 1) ? (column + 1) : 0 
        } 
    } 
    
  3. collectionViewContentSizeの属性を計算する場所です:

    // Using contentWidth and contentHeight, calculate collectionViewContentSize. 
    override var collectionViewContentSize: CGSize { 
        return CGSize(width: contentWidth, height: contentHeight) 
    } 
    
  4. layoutAttributesForElements(in:)

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { 
    
        var visibleLayoutAttributes = [UICollectionViewLayoutAttributes]() 
    
        for attributes in cache { 
         if attributes.frame.intersects(rect) { 
          visibleLayoutAttributes.append(attributes) 
         } 
        } 
        return visibleLayoutAttributes 
    } 
    
  5. layoutAttributesForItem(at:):特定のセル

    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { 
        return cache[indexPath.item] 
    } 
    

のための属性を返すために、レイアウトクラスのgistをチェックしてみて下さい。

ここでは動作しています!私はそれを作るだろうか

Demo

+0

最初のセルには、助けて幸せになりますあなたは手の込んだことができますか?一番上ではなく、右に1 – user6520705

+0

であること –

+0

最初のセルが今すぐ右側の列に表示されますが、可能であれば中央の列が最初に満たされるようにしたいと思いますか? – user6520705

関連する問題