2017-03-16 32 views
1

我有一個UICollectionViewSubclass使用自定義UICOllectionViewLayout如何正確處理UICollectionViewLayout的itemSize的方向變化

如何做最好的我處理方向上的變化改變itemSize?

class CollectSubclass: UICollectionView { 

    /// When orientation changes, then invalidate the layout 
    open override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { 
     super.traitCollectionDidChange(previousTraitCollection) 

     if ((traitCollection.verticalSizeClass != previousTraitCollection?.verticalSizeClass) || (traitCollection.horizontalSizeClass != previousTraitCollection?.horizontalSizeClass)) { 
      collectionViewLayout.invalidateLayout() 
     } 
    } 
} 

一旦佈局的方向變化無效, 我計算細胞的size.width,到UICollectionView的的width

這工作了iPhone 7加模擬器的很好,但未能就小了模擬器像iPhone 7,5,SE等

看來,一旦invalidateLayout被調用時,下面的函數被觸發

/// Lays out subviews. 
override open func layoutSubviews() { 
    super.layoutSubviews() 
} 

該函數依次調用UICollectionViewLayout子類中的prepare函數,其中我使用collectionView的新幀來計​​算單元格的大小。

在iPhone-7-Plus上,traitCollectionDidChange被觸發一次。一旦觸發prepare一次,觸發layoutSubviews

然而,在較小的模擬器上,traitCollectionDidChange被觸發一次,但layoutSubviews被觸發兩次。

在第一次觸發layoutSubviews時,UICO選擇視圖的幀大小爲,幾乎是它應該是什麼。而在第二個觸發器上,UICOllectionView的幀大小現在應該是正確的大小。

被兩次調用兩次不同的框架大小將導致我準備兩次佈局(這是非常昂貴的)。

有沒有從UICOllectionViews和UICollectionViewLayouts子類中錯過的東西?任何幫助表示讚賞。

我也可以在需要時

回答

1

如果在你的設置,你UICollectionViewCells之一的寬度僅基於UICollectionView的大小和屏幕的大小和方向(提供示例項目沒有其他因素),以下是設置集合視圖單元大小的一種簡潔方法:

1)首次加載視圖時,預先計算單元在縱向和橫向上的大小。還要創建一個變量currCellDimensions來保存單元格的當前尺寸,並設置其初始值。

2)重寫功能viewWillTransitionToSize沿着這些路線:

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { 

    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) 
    setCurrentCollectionCellDimensions(size) // This code executes before the rotation begins, but "size" is the size that the main view is going to be after the rotation occurs. As of iOS 8, the size of an object swaps its width and its height when the UI changes its orientation. 
    } 

3)實施setCurrentCollectionCellDimensions():

func setCurrentCollectionCellDimensions(newSize: CGSize) { 

    if (newSize.width < newSize.height) { 
     // set currCellDimensions to what it should be in portrait orientation 
    } else { 
     // set currCellDimension to what it should be in landscape orientation 
    } 

    if collectionView != nil { 

     collectionView.collectionViewLayout.invalidateLayout() // To trigger sizeForItemAtIndexPath to recalculate cell sizes 

    collectionView.reloadData() // To trigger cellForItemAtIndexPath to redraw the cells that are visible to the user. Without this call, the cell layout looks wrong on some iPhones. 
    } 
} 

4)最後,具有sizeForItemAtIndexPath()返回currCellDimensions

+0

嗨,我無法使用'viewWillTransitionToSize'函數,因爲我正在創建一個UICOllectionView子類,而不是UIViewCOntroller子類。我沒有權限訪問ViewController(僅作爲collectionView的弱代理) –

+0

有沒有什麼方法可以在不使用視圖控制器的情況下知道'viewWillTransitionToSize'? –

+0

不,但無論哪種視圖控制器將實例化你的'UICollectionView'子類的實例,你都可以實現'viewWillTransitionToSize()'。然後在'viewWillTransitionToSize()'中,而不是調用'setCurrentCollectionCellDimensions(size)',調用'collectionView.setCurrentCollectionCellDimensions(size)'。你的一些邏輯必須來自視圖控制器,其中一些將成爲你的UICollectionView子類的一部分,但他們可以相互溝通。 – ClayJ