Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UICollectionView items disappear when scrolling with my own UICollectionViewFlowLayout subclass

Context: I am using an UICollectionView for a photoview. Every picture is a cell with one UIImage. Images can have different sizes and I want them to fill the whole screen. So I wrote a class who determines the frame of every single UICollectionCell and let a subclass of UICollectionViewFlowLayout ask that class for the right frame for every item.

My implementation of the UICollectionViewFlowLayoutClass:

override func layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]? {
    let attributesToReturn = super.layoutAttributesForElementsInRect(rect) as? [UICollectionViewLayoutAttributes]
    for attributes in attributesToReturn ?? [] {
        if attributes.representedElementCategory == .Cell {
            let frame = self.layoutAttributesForItemAtIndexPath(attributes.indexPath).frame
            attributes.size = frame.size
            attributes.frame = frame
        }
    }
    return attributesToReturn
}

override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes! {
    let curAttributes = super.layoutAttributesForItemAtIndexPath(indexPath)
    let frame = mazeManager.sizeForItemAtIndex(indexPath, collectionView: collectionView!)
    curAttributes.size = frame.size
    curAttributes.frame = frame
    return curAttributes
}

So the frame asks my MazeManager to give back a frame. The returned frames seem to be correct and they all fit in the UICollectionView.

When I open my app everything looks fine, even when I scroll. But when I scroll to a specific position (this position feels random because it depends on the images I test with, but with the same set of images the positions are the same) cells disappear from my view. When I scroll back they return.

I've checked if the cells where not hidden, but they never are.

On some other threads with similar issues the answer is to implement the collectionViewContentSize so I did:

override func collectionViewContentSize() -> CGSize {
    let size = mazeManager.collectionViewContentSize
    return size.height < collectionView!.frame.size.height ? collectionView!.frame.size : size
}

The number of items is not static and it grows while reaching the end of the view. So what happens here is: The manager determines the Origin.y + the Size.Height of the last item (+ 10 points to be sure), the width is the width of the UICollectionView.

Still all the frames of the cells are within the sizes returned by this method. But still some cell disappear or never appear at all.

When I scroll further through the UICollectionView I see other cells which are positioned on the right place. So there are gaps in my view, but the flow continues. (When a gap appears there are no calls for the items at the missing idexpaths in the collectionViewDelegate. For example the CollectionView asks for items: 1,2,3,4,5,6, 12,13,14).

The console prints nothing about wrong positioning, I've checked and everything is within the ContentSize. So I'm almost out of options. Can anybody explain what's happening in my case?

Thank you.

Edit:

While I was looking for a solution, I already found the mentioned post (UICollectionView's cell disappearing) and I already did 3 of the 4 steps.

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

And I just added the scroll direction in the initializer:

override init(){
    super.init()
    scrollDirection = .Vertical
}

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    self.scrollDirection = .Vertical
}

Unfortunately this doesn't fix my issue, so it doesn't seem a duplicate to me.

like image 463
Aron K. Avatar asked Apr 21 '15 17:04

Aron K.


1 Answers

I don't know why, but it works when I add the following line in my init methods:

    self.itemSize = CGSize(width: 165,height: 165)

165 is the average height for my cells (I need to make this less static). The size I specified here seems to be ignored, because the sizes I see on my screen are all calculated in the layoutAttributesForItemAtIndexPath.

So without this property set the view behaves strange, I still don't know the reason, but I'm glad it works. (If anyone knows the reason, I would like to hear it)

like image 166
Aron K. Avatar answered Oct 04 '22 21:10

Aron K.