2017-08-06 164 views
1

我試圖創建一個UICollectionView,所有單元格100%可見,這樣我就不需要滾動來查看它們。我目前正在嘗試顯示一個3x3的網格,並在運行中計算單元格的大小。UICollectionView不滾動

我有一個容器視圖中的標題CollectionView和UIView。標題固定在容器頂部,高度爲100px。 CollectionView低於此值,固定到每一面,底部,並將其頂部固定到標題底部。

當我使用sizeForItemAt時,我試圖找到可見區域的大小,將它分成1/3大小的塊(除了填充/插入)。我的代碼如下所示:

func collectionView(_ collectionView: UICollectionView, 
        layout collectionViewLayout: UICollectionViewLayout, 
        sizeForItemAt indexPath: IndexPath) -> CGSize { 

    let numRows = self.numRows() 
    let itemsPerRow = self.itemsPerRow() 

//  let frameSize = collectionView.frame.size 
    let frameSize = collectionView.bounds.size 
//  let frameSize = collectionView.collectionViewLayout.collectionViewContentSize 
//  let frameSize = collectionView.intrinsicContentSize 

    let totalItemPadding = self.itemPadding * (itemsPerRow - 1) 
    let totalLinePadding = self.linePadding * (numRows - 1) 

    let availableWidth = frameSize.width - totalItemPadding 
    var widthPerItem = availableWidth/itemsPerRow 

    let availableHeight = frameSize.height - totalLinePadding 
    var heightPerItem = availableHeight/numRows 

    return CGSize(width: widthPerItem, height: heightPerItem) 
} 

結果始終是第3行的一半左右被遮蔽的,因爲它看起來像框架尺寸爲「高」比實際顯示在模擬器。

The bottom row is chopped in half vertically

有什麼在UICollectionView這會給我的可見大小?我在佈局時間方面錯誤的時間,還是應該添加另一種方法,在某些時候使尺寸無效?

我還沒有找到任何教程顯示所有項目的集合視圖,並且不垂直滾動,所以任何其他指針(甚至是類似這樣的庫)都將不勝感激。

謝謝!

+0

,它必須得到一個UICollectionView?基於你的描述你想要什麼我想你會更好使用嵌套StackViews – TMin

+0

你應該使用集合視圖中的節標題;) – John

回答

1

你確定這個方法被調用嗎?在這個例程中添加一個日誌語句或一個斷點,並確保它被調用。

如果你忽略正式聲明你的視圖控制器符合UICollectionViewDelegateFlowLayout,一個常見的問題可能會阻止它被調用。在這種情況下,它將使用它在故事板中找到的任何內容。但我這樣做的時候,你的代碼工作對我很好,例如:

extension ViewController: UICollectionViewDelegateFlowLayout { 

    func collectionView(_ collectionView: UICollectionView, 
         layout collectionViewLayout: UICollectionViewLayout, 
         sizeForItemAt indexPath: IndexPath) -> CGSize { 
     let numRows = self.numRows() 
     let itemsPerRow = self.itemsPerRow() 

     let frameSize = collectionView.bounds.size 

     let layout = collectionViewLayout as! UICollectionViewFlowLayout 

     let totalItemPadding = layout.minimumInteritemSpacing * (itemsPerRow - 1) 
     let totalLinePadding = layout.minimumInteritemSpacing * (numRows - 1) 

     let availableWidth = frameSize.width - totalItemPadding 
     let widthPerItem = availableWidth/itemsPerRow 

     let availableHeight = frameSize.height - totalLinePadding 
     let heightPerItem = availableHeight/numRows 

     return CGSize(width: widthPerItem, height: heightPerItem) 

    } 
} 

請注意,我用的也是minimumInteritemSpacing,所以我使用現有的間隔參數,而不是定義自己。它使我更好地使用現有的參數(尤其是可以在IB中設置的參數)。


順便說一句,作爲替代,如果它總是將是在一個屏幕上,就是用自己的自定義佈局,而不是流佈局。這樣你就不會糾結集合視圖的委託與許多繁瑣的代碼。它會更復用一點。例如:

class GridLayout: UICollectionViewLayout { 

    var itemSpacing: CGFloat = 5 
    var rowSpacing: CGFloat = 5 

    private var itemSize: CGSize! 
    private var numberOfRows: Int! 
    private var numberOfColumns: Int! 

    override func prepare() { 
     super.prepare() 

     let count = collectionView!.numberOfItems(inSection: 0) 

     numberOfColumns = Int(ceil(sqrt(Double(count)))) 
     numberOfRows = Int(ceil(Double(count)/Double(numberOfColumns))) 

     let width = (collectionView!.bounds.width - (itemSpacing * CGFloat(numberOfColumns - 1)))/CGFloat(numberOfColumns) 
     let height = (collectionView!.bounds.height - (rowSpacing * CGFloat(numberOfRows - 1)))/CGFloat(numberOfRows) 
     itemSize = CGSize(width: width, height: height) 
    } 

    override var collectionViewContentSize: CGSize { 
     return collectionView!.bounds.size 
    } 

    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { 
     let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath) 

     attributes.center = centerForItem(at: indexPath) 
     attributes.size = itemSize 

     return attributes 
    } 

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { 
     return (0 ..< collectionView!.numberOfItems(inSection: 0)).map { IndexPath(item: $0, section: 0) } 
      .flatMap { layoutAttributesForItem(at: $0) } 
    } 

    private func centerForItem(at indexPath: IndexPath) -> CGPoint { 

     let row = indexPath.item/numberOfColumns 
     let col = indexPath.item - row * numberOfColumns 

     return CGPoint(x: CGFloat(col) * (itemSize.width + itemSpacing) + itemSize.width/2, 
         y: CGFloat(row) * (itemSize.height + rowSpacing) + itemSize.height/2) 
    } 

    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { 
     return true 
    } 
} 

,然後在視圖控制器:

override func viewDidLoad() { 
    super.viewDidLoad() 

    let layout = GridLayout() 
    layout.itemSpacing = 10 
    layout.rowSpacing = 5 
    collectionView?.collectionViewLayout = layout 
} 
+0

Dude。DUDE。網格佈局是第一次嘗試 - 你寫了那個,還是你找到它的地方?如果你寫了它,我欠你一瓶啤酒,如果你找到它,你能指點我到哪裏 – Hoopes

+0

此外,代碼確實被調用,我有所有的類設置正確,我只是想不通爲什麼'collectionView.bounds.size'和/或'collectionView .frame.size'沒有給我正確的高度。 – Hoopes

+0

你是什麼意思,如果它是將在一個單一的屏幕上?我想在某個時候用箭頭按鈕實現分頁,我是否將自己繪製到網格佈局的角落? – Hoopes

1

對於版面大小,你可以使用UICollectionViewFlowLayout和涉及的尺寸在屏幕寬度和高度的條款,以保護UICollectionView.見的網格樣式的外觀:https://developer.apple.com/documentation/uikit/uicollectionviewflowlayouthttps://www.raywenderlich.com/136159/uicollectionview-tutorial-getting-started

至於滾動問題,請檢查您的滾動功能是否啓用,您的約束設置是否正確,並且您沒有在此鏈接中提到的問題。 UICollectionView does not scroll

祝你好運! :)

+0

嗨,我很抱歉,我不是更清楚。我實際上並不想要滾動視圖 - 我想要在屏幕上顯示所有內容(全尺寸),所以我不必滾動。我原本是通過嵌套堆棧視圖來完成這項工作的,但收集視圖的靈活性似乎很有吸引力(我喜歡ios編程兩週,fwiw) – Hoopes

1

您滾動不工作,因爲視圖是屏幕的只是大小...

只是爲了讓招加1000的偏移的CollectionView的總高度的量是每row *(row.size.height + padding)。

+0

嗨,John,謝謝你的迴應。我關閉了滾動 - 我想查看集合視圖中的所有單元而不滾動。在截圖中,你可以看到最後一行被切斷,我試圖找出原因(我花了一整天的時間想弄清楚爲什麼'collectionView.frame'高度不正確 - 我很確定我的數學是 – Hoopes

+0

我不能在接下來的幾個小時來檢查,但你應該打印你的閥值得到的錯誤,我同意數學似乎罰款。我會做的第一件事是使用self.view和從尺寸...我將會在以後檢查 – John