UICollectionView Decoration and Supplementary view

2019-03-09 15:35发布

In UICollectionView decoration and supplementary views seem to be a big mystery. There seems to be next to no example code at the moment. I managed to get both types working in a custom layout (see this post for some details). As long as they remain in the same position everything is fine (i.e. if their layoutAttributes.frame does not change).

However as soon as I re-layout with changed layoutAttributes for either decoration or supplementary views they get visually duplicated - i.e. there is a copy in the background at their original location and a copy at their new location. The behaviour is identical if I instantiate them from XIBs or completely in code and the behaviour does not occur for normal cells.

At first I thought that it is some kind of redraw problem, but these "copies" survive re-layouting, redrawing etc. They are not real copies however, since the layoutAttributesForDecorationView etc. are never called for them (only for the new locations). There seems to be some caching in the background in the UICollectionView.

Has anybody got this working or have any ideas. I must say that I am new to the iOS platform, so it could also be simple things like setting the "Clips Bound" or "Clear Graphics Context" properties (I tried those, but it could be something similar).

This is driving me crazy and it is strange that there is absolutely no example code out there.

I am asking myself: Are the decoration and supplementary views not meant to be repositioned? (I hope not)

5条回答
放荡不羁爱自由
2楼-- · 2019-03-09 15:59

I had a similar symptom. My problem was that I had accidentally included the supplementary view's reuseID instead of the kindID when creating my custom layout.

Specifically I had this (Wrong)

UICollectionViewLayoutAttributes *attributes = 
  [UICollectionViewLayoutAttributes
    layoutAttributesForSupplementaryViewOfKind:myViewReuseID
    withIndexPath:sectionIndexPath];

When I should have this (Right)

UICollectionViewLayoutAttributes *attributes = 
  [UICollectionViewLayoutAttributes
    layoutAttributesForSupplementaryViewOfKind:myViewKindID
    withIndexPath:sectionIndexPath];

This meant that prepareForReuse was never getting called, and my old views never went away. Instead they kept piling up.

查看更多
虎瘦雄心在
3楼-- · 2019-03-09 16:03

I think Apple is going to indicate at least in the case of Decoration views that they are working as intended. I ran into this same problem as I was re-sizing the last section and trying to setup the Decoration view to surround the sections as they changed. Using a simple view at first that just had a red background the entire background of my app became red and this confused me. I subsequently changed the alpha to 0.3f on the layout attributes of the decoration views and I was able to see them layer upon each other as the sections changed.

What really tipped me off that this might be by design though was a line I read in a tutorial on UICollectionView

On the other hand, decoration views are “ornamental” rather than data-driven: think of the bookshelf backdrop in the iBooks app.

The key is that Decoration Views aren't data-driven and shouldn't be changing as your data changes regardless of if you being able to do this in the custom layout. Like in the case of a bookshelf the size of the shelves don't change after they've been created.

查看更多
霸刀☆藐视天下
4楼-- · 2019-03-09 16:10

I had the same issue. it's seems that there are some bugs with the UICOllectionview (this is not the first I saw). I fixed it by not using "performBatchUpdates". I lose the animation - but at list there are no unwanted view.

查看更多
smile是对你的礼貌
5楼-- · 2019-03-09 16:14

Hi this is an old question but there is an answer for it.

Actually I had these issues too when I implemented my own Layout object, until I realised it is imperative to cache any layout attributes objects you create in your custom layout. There is actually a very vague reference to this in the documentation (I can't remember the precise location now) which is very easily misinterpreted.

Essentially once you have requested a layoutAttributes object for a cell at an index path, you should retain the attributes object (e.g. retaining it in a dictionary with the index path as a key will do) and return the same attributes object for any and all subsequent requests for the attributes. If you don't do this, but instead recreate new layout attributes, animation of batch updates results in severe graphical glitches and artefacts.

查看更多
Summer. ? 凉城
6楼-- · 2019-03-09 16:23

I know this is an old question but I came across this when having problems with supplementary views being duplicated all over the place when invalidating a layout. I believe it's a bug, and I fixed it by ove-riding invalidateLayout in my layout object and removing the supplementary views as below:

- (void)invalidateLayout {
    [super invalidateLayout];
    // Manually remove all suplementary views of a certain type
    /**
     ** This appears to be a BUG. Invalidate view does not remove suplementary view
     **     from the view hierachy. But they are Orphaned so stay on screen. 
     **/
    for (UIView *subview in [self.collectionView subviews]) {
        if ([subview isKindOfClass:[UICollectionReusableView class]]) {
            [subview removeFromSuperview];
        }
    }
}

Replace UICollectionReusableView with the class of your re-usable view that is being left on screen.

Hope this helps someone.

查看更多
登录 后发表回答