How to add a background image to UICollectionView that will scroll and zoom will cells

后端 未结 2 1895
独厮守ぢ
独厮守ぢ 2021-01-02 20:24

I\'m building a mosaic view using UICollectionView.

I have subclassed UICollectionViewFlowLayout to layout a fixed grid that can be scrolle

相关标签:
2条回答
  • 2021-01-02 20:51

    Don't know if you found an answer...!

    You're on the right track with wanting to use supplementary views. The index path of the supplementary view isn't tied to a cell, it has its own index path.

    Then in your subclass of UICollectionViewFlowLayout you need to subclass a few methods. The docs are pretty good!

    In the layoutAttributesForElementsInRect: method you'll need to call super and then add another set of layout attributes for your supplementary view.

    Then in the layoutAttributesForSupplementaryViewOfKind:atIndexPath: method you set the size of the returned attributes to the size of the collection view content so the image fills all the content, and not just the frame. You also probably want to set the z-order to, to make sure it's behind the cells. See the docs for UICollectionViewLayoutAttributes

    @implementation CustomFlowLayout
    
        -(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
        {
            NSMutableArray *attributes = [[super layoutAttributesForElementsInRect:rect] mutableCopy];
    
            // Use your own index path and kind here
            UICollectionViewLayoutAttributes *backgroundLayoutAttributes = [self layoutAttributesForSupplementaryViewOfKind:@"background" atIndexPath:[NSIndexPath indexPathWithItem:0 inSection:0]];
    
            [attributes addObject:backgroundLayoutAttributes];
    
            return [attributes copy];
        }
    
        -(UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
    
            if ([kind isEqualToString:@"background"]) {
                UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:kind withIndexPath:indexPath];
                attrs.size = [self collectionViewContentSize];
                attrs.zIndex = -10;
                return attrs;
            } else {
                return [super layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:indexPath];
            }
        }
    
    @end
    

    In your collection view data source you need this method: collectionView:viewForSupplementaryElementOfKind:atIndexPath:

    -(void)viewDidLoad
    {
        [super viewDidLoad];
    
        // Setup your collection view
        UICollectionView *collectionView = [UICollectionView initWithFrame:self.view.bounds collectionViewLayout:[CustomFlowLayout new]];
        [collectionView registerClass:[BackgroundReusableView class] forSupplementaryViewOfKind:@"background" withReuseIdentifier:@"backgroundView"];
    }
    
    - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
    {
        if ([kind isEqualToString:@"background"]) {
            BackgroundReusableView *view = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"backgroundView" forIndexPath:indexPath];
    
            // Set extra info
    
            return view;
        } else {
            // Shouldn't be called
            return nil;
        }
    }
    

    Hopefully all that should get you on the right track :)

    0 讨论(0)
  • 2021-01-02 21:07

    To implement custom section background in CollectionView in Swift 5,

    class CustomFlowLayout: UICollectionViewFlowLayout {
    
        override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
            var attributes = super.layoutAttributesForElements(in: rect)
            
            for section in 0..<collectionView!.numberOfSections{
                let backgroundLayoutAttributes:UICollectionViewLayoutAttributes = layoutAttributesForSupplementaryView(ofKind: "background", at: IndexPath(item: 0, section: section)) ?? UICollectionViewLayoutAttributes()
                attributes?.append(backgroundLayoutAttributes)
            }
            return attributes
        }
        
        override func layoutAttributesForSupplementaryView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
            let attrs = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: elementKind, with: indexPath)
            if elementKind == "background"{
                attrs.size = collectionView!.contentSize
                
                //calculate frame here
                let items = collectionView!.numberOfItems(inSection: indexPath.section)
                let totalSectionHeight:CGFloat = CGFloat(items * 200)
                let cellAttr = collectionView!.layoutAttributesForItem(at: indexPath)
                attrs.frame = CGRect(x: 0, y: cellAttr!.frame.origin.y, width: collectionView!.frame.size.width, height: totalSectionHeight)
                
                attrs.zIndex = -10
                return attrs
            }else{
                return super.layoutAttributesForSupplementaryView(ofKind: elementKind, at: indexPath)
            }
        }
    }
    

    In your CollectionView DataSource,

              override func viewDidLoad() {
                super.viewDidLoad()
        
                //register collection view here
               ...
    
                //setup flow layout & register supplementary view        
                let customFlowLayout = CustomFlowLayout()
                collectionView.collectionViewLayout = customFlowLayout
                collectionView.register(UINib(nibName: "BackgroundReusableView", bundle: nil), forSupplementaryViewOfKind: "background", withReuseIdentifier: "BackgroundReusableView")
    
    
    }
    
    
        func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
                if kind == "background"{
                    let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "BackgroundReusableView", for: indexPath) as! BackgroundReusableView
                    return view
                }
                return UICollectionReusableView()
            }
    
    0 讨论(0)
提交回复
热议问题