UICollectionView horizontal paging - can I use Flo

2019-01-20 23:20发布

This is related to but distinct from To use Flow Layout, or to Customize?.

Here is an illustration of what I’m trying to do: Illustration of what I’m trying to do

I’m wondering if I can do this with a UICollectionViewFlowLayout, a subclass thereof, or if I need to create a completely custom layout? Based on the WWDC 2012 videos on UICollectionView, it appears that if you use Flow Layout with vertical scrolling, your layout lines are horizontal, and if you scroll horizontally, your layout lines are vertical. I want horizontal layout lines in a horizontally-scrolling collection view.

I also don’t have any inherent sections in my model - this is just a single set of items. I could group them into sections, but the collection view is resizable, so the number of items that can fit on a page would change sometimes, and it seems like the choice of which page each item goes on is better left to the layout than to the model if I don’t have any meaningful sections.

So, can I do this with Flow Layout, or do I need to create a custom layout?

8条回答
趁早两清
2楼-- · 2019-01-21 00:00

Converted vilanovi code to Swift in case someone, needs it in the future.

public class HorizontalCollectionViewLayout : UICollectionViewLayout {
private var cellWidth = 90 // Don't kow how to get cell size dynamically
private var cellHeight = 90

public override func prepareLayout() {
}

public override func collectionViewContentSize() -> CGSize {
    let numberOfPages = Int(ceilf(Float(cellCount) / Float(cellsPerPage)))
    let width = numberOfPages * Int(boundsWidth)
    return CGSize(width: CGFloat(width), height: boundsHeight)
}

public override func layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]? {
    var allAttributes = [UICollectionViewLayoutAttributes]()

    for (var i = 0; i < cellCount; ++i) {
        let indexPath = NSIndexPath(forRow: i, inSection: 0)
        let attr = createLayoutAttributesForCellAtIndexPath(indexPath)
        allAttributes.append(attr)
    }

    return allAttributes
}

public override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes! {
    return createLayoutAttributesForCellAtIndexPath(indexPath)
}

public override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool {
    return true
}

private func createLayoutAttributesForCellAtIndexPath(indexPath:NSIndexPath)
    -> UICollectionViewLayoutAttributes {
        let layoutAttributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)
        layoutAttributes.frame = createCellAttributeFrame(indexPath.row)
        return layoutAttributes
}

private var boundsWidth:CGFloat {
    return self.collectionView!.bounds.size.width
}

private var boundsHeight:CGFloat {
    return self.collectionView!.bounds.size.height
}

private var cellCount:Int {
    return self.collectionView!.numberOfItemsInSection(0)
}

private var verticalCellCount:Int {
    return Int(floorf(Float(boundsHeight) / Float(cellHeight)))
}

private var horizontalCellCount:Int {
    return Int(floorf(Float(boundsWidth) / Float(cellWidth)))
}

private var cellsPerPage:Int {
    return verticalCellCount * horizontalCellCount
}

private func createCellAttributeFrame(row:Int) -> CGRect {
    let frameSize = CGSize(width:cellWidth, height: cellHeight )
    let frameX = calculateCellFrameHorizontalPosition(row)
    let frameY = calculateCellFrameVerticalPosition(row)
    return CGRectMake(frameX, frameY, frameSize.width, frameSize.height)
}

private func calculateCellFrameHorizontalPosition(row:Int) -> CGFloat {
    let columnPosition = row % horizontalCellCount
    let cellPage = Int(floorf(Float(row) / Float(cellsPerPage)))
    return CGFloat(cellPage * Int(boundsWidth) + columnPosition * Int(cellWidth))
}

private func calculateCellFrameVerticalPosition(row:Int) -> CGFloat {
    let rowPosition = (row / horizontalCellCount) % verticalCellCount
    return CGFloat(rowPosition * Int(cellHeight))
}

}

查看更多
Fickle 薄情
3楼-- · 2019-01-21 00:01

Your last resort, of course, would be to use multiple vertically collection views inside each section in an outer horizontally scrolling collection view. Apart from increasing code complexity and difficulty in performing inter-section cell animations, I can't think of major issues with this approach right off my head.

查看更多
登录 后发表回答