如何将背景图像添加到 UICollectionView 将滚动和缩放单元格

Posted

技术标签:

【中文标题】如何将背景图像添加到 UICollectionView 将滚动和缩放单元格【英文标题】:How to add a background image to UICollectionView that will scroll and zoom will cells 【发布时间】:2014-01-16 12:29:40 【问题描述】:

我正在使用UICollectionView 构建马赛克视图。

我已将UICollectionViewFlowLayout 子类化为布局一个可以水平和垂直滚动 的固定网格。我还附上了一个UIPinchGestureRecognizer,以便集合可以缩放/缩放。

集合中的每个单元格都包含一个具有一定透明度的UIImage。我想添加一个可以随单元格滚动和缩放的背景图像。

我尝试了许多不同的解决方案。

使用colorWithPatternImage设置UICollectionView的背景颜色。 (不随内容滚动/调整大小) 将每个单元格上的背景图像视图设置为背景图像的相关裁剪部分。 (占用太多内存

我一直在研究补充和装饰视图,但很难理解它。我想我需要使用 Supplementary 视图,因为背景中使用的图像会根据datasource 而改变。

我不明白的是如何只注册一个补充视图来跨越整个collectionview 的宽度和高度。它们似乎与indexPath 即每个单元格相关联。

【问题讨论】:

一个潜在的解决方案可能是将图像放在集合视图后面的滚动视图中,并且每次用户滚动集合视图时,您手动设置背景滚动视图以匹配。 感谢@nhgrif,这是我考虑过的一种解决方案,但似乎有点不雅。 【参考方案1】:

不知道你有没有找到答案...!

您想要使用补充视图的方法是正确的。补充视图的索引路径不绑定到单元格,它有自己的索引路径。

然后在UICollectionViewFlowLayout 的子类中,您需要对一些方法进行子类化。 docs 还不错!

layoutAttributesForElementsInRect: 方法中,您需要调用 super,然后为补充视图添加另一组布局属性。

然后在layoutAttributesForSupplementaryViewOfKind:atIndexPath: 方法中,将返回属性的大小设置为集合视图内容的大小,以便图像填充所有内容,而不仅仅是框架。您可能还想将 z 顺序设置为,以确保它位于单元格后面。请参阅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

在您的集合视图数据源中,您需要此方法: 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;
    

希望所有这些都能让你走上正轨:)

【讨论】:

感谢 Rich 的帮助,太好了,我会试一试!【参考方案2】:

在 Swift 5 中实现 CollectionView 中的自定义部分背景,

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)
        
    

在您的 CollectionView 数据源中,

          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()
        

【讨论】:

以上是关于如何将背景图像添加到 UICollectionView 将滚动和缩放单元格的主要内容,如果未能解决你的问题,请参考以下文章

如何将背景图像添加到活动?

如何将背景图像添加到 UICollectionView 将滚动和缩放单元格

如何将图像背景添加到不透明的文本中? [复制]

如何使用 swift 将相同的背景图像添加到我的 ios 应用程序中的所有视图?

如何使用自定义钩子访问织物对象以将背景图像添加到画布?

如何在不影响 Pyqt5 中的小部件的情况下将背景图像添加到主窗口