Iphone 如何在UICollectionView中的UICollectionViewCells之间添加视图?

Iphone 如何在UICollectionView中的UICollectionViewCells之间添加视图?,iphone,ios,objective-c,uicollectionview,uicollectionviewcell,Iphone,Ios,Objective C,Uicollectionview,Uicollectionviewcell,我正在尝试在我的UICollectionView中的UICollectionViewCells之间添加UIViews,我不知道如何才能做到这一点。我正在努力完成这样的事情: 我可能需要编写一个自定义的UICollectionViewLayout,但我真的不知道从哪里开始。如果您使用的是节,并且布局适合它,您可能会使用节页眉和页脚 但是根据您的说明,看起来您只需要定义UICollectionViewCell来包含这些视图。那么,在哪里注册您的课程: [collectionView registe

我正在尝试在我的
UICollectionView
中的
UICollectionViewCell
s之间添加
UIView
s,我不知道如何才能做到这一点。我正在努力完成这样的事情:


我可能需要编写一个自定义的
UICollectionViewLayout
,但我真的不知道从哪里开始。

如果您使用的是节,并且布局适合它,您可能会使用节页眉和页脚

但是根据您的说明,看起来您只需要定义UICollectionViewCell来包含这些视图。那么,在哪里注册您的课程:

[collectionView registerClass:[CollectionViewCell class] forCellWithReuseIdentifier:@"Cell"];
将这些边框图像放入UICollectionView单元格子类(在上面的示例中为“CollectionViewCell”)。这似乎是最简单的方法

我用的是:

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        self.restorationIdentifier = @"Cell";
        self.backgroundColor = [UIColor clearColor];
        self.autoresizingMask = UIViewAutoresizingNone;
        const CGFloat borderWidth = 3.0f;
        UIView *bgView = [[UIView alloc] initWithFrame:frame];
        bgView.layer.borderColor = [UIColor blackColor].CGColor;
        bgView.layer.borderWidth = borderWidth;
        bgView.layer.cornerRadius = 6.0f;
        self.selectedBackgroundView = bgView;
    }
    return self;
}

看起来,如果collectionView背景为绿色,contentView背景为白色,则可以得到单元格之间有空格的水平面。垂直间隙可能是一个棘手的部分,但是如果你对contentView有创意,并且仔细设置,你可以得到它。

我更多地研究了UICollectionViewLayout的工作原理,并找到了解决方法。我有一个名为
OrangeView
UICollectionReusableView
子类,它将位于我的视图之间,而我编写了一个名为
CategoriesLayout
UICollectionViewFlowLayout
子类,它将处理我的布局

抱歉,代码太多,但下面是它的样子:

@implementation CategoriesLayout

- (void)prepareLayout {
    // Registers my decoration views.
    [self registerClass:[OrangeView class] forDecorationViewOfKind:@"Vertical"];
    [self registerClass:[OrangeView class] forDecorationViewOfKind:@"Horizontal"];
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind atIndexPath:(NSIndexPath *)indexPath {
    // Prepare some variables.
    NSIndexPath *nextIndexPath = [NSIndexPath indexPathForItem:indexPath.row+1 inSection:indexPath.section];

    UICollectionViewLayoutAttributes *cellAttributes = [self layoutAttributesForItemAtIndexPath:indexPath];
    UICollectionViewLayoutAttributes *nextCellAttributes = [self layoutAttributesForItemAtIndexPath:nextIndexPath];

    UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:decorationViewKind withIndexPath:indexPath];

    CGRect baseFrame = cellAttributes.frame;
    CGRect nextFrame = nextCellAttributes.frame;

    CGFloat strokeWidth = 4;
    CGFloat spaceToNextItem = 0;
    if (nextFrame.origin.y == baseFrame.origin.y)
        spaceToNextItem = (nextFrame.origin.x - baseFrame.origin.x - baseFrame.size.width);

    if ([decorationViewKind isEqualToString:@"Vertical"]) {
        CGFloat padding = 10;

        // Positions the vertical line for this item.
        CGFloat x = baseFrame.origin.x + baseFrame.size.width + (spaceToNextItem - strokeWidth)/2;
        layoutAttributes.frame = CGRectMake(x,
                                            baseFrame.origin.y + padding,
                                            strokeWidth,
                                            baseFrame.size.height - padding*2);
    } else {
        // Positions the horizontal line for this item.
        layoutAttributes.frame = CGRectMake(baseFrame.origin.x,
                                            baseFrame.origin.y + baseFrame.size.height,
                                            baseFrame.size.width + spaceToNextItem,
                                            strokeWidth);
    }

    layoutAttributes.zIndex = -1;
    return layoutAttributes;
}

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
    NSArray *baseLayoutAttributes = [super layoutAttributesForElementsInRect:rect];
    NSMutableArray * layoutAttributes = [baseLayoutAttributes mutableCopy];

    for (UICollectionViewLayoutAttributes *thisLayoutItem in baseLayoutAttributes) {
        if (thisLayoutItem.representedElementCategory == UICollectionElementCategoryCell) {
            // Adds vertical lines when the item isn't the last in a section or in line.
            if (!([self indexPathLastInSection:thisLayoutItem.indexPath] ||
                  [self indexPathLastInLine:thisLayoutItem.indexPath])) {
                UICollectionViewLayoutAttributes *newLayoutItem = [self layoutAttributesForDecorationViewOfKind:@"Vertical" atIndexPath:thisLayoutItem.indexPath];
                [layoutAttributes addObject:newLayoutItem];
            }

            // Adds horizontal lines when the item isn't in the last line.
            if (![self indexPathInLastLine:thisLayoutItem.indexPath]) {
                UICollectionViewLayoutAttributes *newHorizontalLayoutItem = [self layoutAttributesForDecorationViewOfKind:@"Horizontal" atIndexPath:thisLayoutItem.indexPath];
                [layoutAttributes addObject:newHorizontalLayoutItem];
            }
        }
    }

    return layoutAttributes;
}

@end
我还编写了一个类别,其中包含一些方法来检查索引路径是一行中的最后一行、最后一行还是一节中的最后一行:

@implementation UICollectionViewFlowLayout (Helpers)

- (BOOL)indexPathLastInSection:(NSIndexPath *)indexPath {
    NSInteger lastItem = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:indexPath.section] -1;
    return  lastItem == indexPath.row;
}

- (BOOL)indexPathInLastLine:(NSIndexPath *)indexPath {
    NSInteger lastItemRow = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:indexPath.section] -1;
    NSIndexPath *lastItem = [NSIndexPath indexPathForItem:lastItemRow inSection:indexPath.section];
    UICollectionViewLayoutAttributes *lastItemAttributes = [self layoutAttributesForItemAtIndexPath:lastItem];
    UICollectionViewLayoutAttributes *thisItemAttributes = [self layoutAttributesForItemAtIndexPath:indexPath];

    return lastItemAttributes.frame.origin.y == thisItemAttributes.frame.origin.y;
}

- (BOOL)indexPathLastInLine:(NSIndexPath *)indexPath {
    NSIndexPath *nextIndexPath = [NSIndexPath indexPathForItem:indexPath.row+1 inSection:indexPath.section];

    UICollectionViewLayoutAttributes *cellAttributes = [self layoutAttributesForItemAtIndexPath:indexPath];
    UICollectionViewLayoutAttributes *nextCellAttributes = [self layoutAttributesForItemAtIndexPath:nextIndexPath];

    return !(cellAttributes.frame.origin.y == nextCellAttributes.frame.origin.y);
}

@end
这是最终的结果:


哇。其他答案中有很多代码,只是为了行之间的分隔线

我就是这样解决的。首先,需要在单元格内添加行分隔符。确保一直拖动它,使其比实际单元格宽度宽,因此如果单元格宽度为60p,分隔线将为70

@implementation CollectionViewController
{
    NSArray *test;
    int currentLocInRow;
}
内部
单元ForItemAtIndexPath

if((indexPath.row+1) % 4 == 0)
    {
        cell.clipsToBounds = YES;
    }
    else
    {
        cell.clipsToBounds = NO;
    }
    currentLocInRow++;

    if([test count] - indexPath.row+1 < 4 - currentLocInRow)
    {
        cell.lineSeparator.alpha = 0;
    }
    else
    {
        cell.lineSeparator.alpha = 1;
    }
    if(currentLocInRow==4)currentLocInRow=0;
if((indexPath.row+1)%4==0)
{
cell.clipstobunds=是;
}
其他的
{
cell.clipstobunds=否;
}
currentLocInRow++;
if([test count]-indexPath.row+1<4-currentLocInRow)
{
cell.lineSeparator.alpha=0;
}
其他的
{
cell.lineSeparator.alpha=1;
}
如果(currentLocInRow==4)currentLocInRow=0;


如果希望在集合视图的末尾使用分隔符,但最后一行可能没有4个单元格,则可以添加一个简单的集合可重用视图作为页脚。

节不适用。我需要知道,如果这是这行的最后一个单元格,我不应该在右边显示这行。我想要一个可以旋转甚至可以在iPad上重复使用的集合视图,在iPad上,单元格之间的距离会有所不同。您可以通过UICollectionViewDelegateFlowLayout协议的方法控制布局的间距和大小(无论目标设备或方向如何)。如果单元格结构正确,就没有理由不能根据单元格的indexPath以任何方式控制边框视图。最棘手的部分是在同一行中的项目之间设置分隔符,并使其独立于容器大小工作(当您旋转或在iPad上时)@MarcoPompei我只需要为我正在开发的应用程序实现行下的行。如果我需要在项目之间添加分隔符,我会在这里发布我的解决方案(如果我能找到更好的解决方案…)这是一个很好的问题。虽然代码较少,但不应该鼓励这样做。这显然是一种只“解决”50%问题的黑客行为。当从底部移除单元格时,此代码不会移除分隔符,有什么方法可以做到吗?@Kronusdark尝试在集合视图布局上调用
-invalidateLayout
,查看是否强制重画所有内容。我还并没有测试过它,不确定它是否有效……这是有效的,但它会挂起一秒钟,我将不得不玩计时方法。非常感谢您的快速回复reply@Kronusdark是的,我以为会发生的。我检查了,检查了要覆盖的方法,其中六个涉及添加和删除项,实现它们应该是可行的。也许我回家后会尝试更新此代码,但我不能向您保证任何事情。太难理解了,如果有源项目下载链接,会更好