Подтвердить что ты не робот

Как добавить представления между UICollectionViewCells в UICollectionView?

Я пытаюсь добавить UIView между моим UICollectionViewCell в my UICollectionView, и я не знаю, как это сделать. Я пытаюсь выполнить что-то вроде этого:

Screenshot

Мне, вероятно, понадобится написать пользовательский UICollectionViewLayout, но я не знаю, с чего начать.

4b9b3361

Ответ 1

Я больше изучил работу UICollectionViewLayout и выяснил, как ее решить. У меня есть подкласс UICollectionReusableView под названием OrangeView, который будет размещен между моими представлениями, чем я написал подкласс UICollectionViewFlowLayout под названием CategoriesLayout, который будет обрабатывать мой макет.

Извините за большой блок кода, но вот как он выглядит:

@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

И это конечный результат:

Final Result

Ответ 2

Если вы используете разделы и макет подходит для него, вы можете использовать заголовки и нижние колонтитулы раздела.

Но на основе вашей иллюстрации, похоже, вам просто нужно определить 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;
}

Ответ 3

Похоже, если ваш фон коллекцииView был зеленым и contentView white, вы могли бы получить горизонтали с пробелом между ячейками minimumLineSpacing. Вертикальный промежуток был бы сложной частью, но если бы вы были креативны с вашим contentView и аккуратно установили minimumInteritemSpacing, вы могли бы получить его.

Ответ 4

Ого. То, что много кода в другом отвечает только для разделительной строки между строками.

Вот как я это решил. Сначала вам нужно будет добавить разделитель строк внутри ячейки. Удостоверьтесь, что вы продолжаете перетаскивать его, делая его шире, чем фактическая ширина ячейки, поэтому, если ширина ячейки составляет 60p, ваша разделительная линия будет равна 70.

@implementation CollectionViewController
{
    NSArray *test;
    int currentLocInRow;
}

внутри cellForItemAtIndexPath:

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;

enter image description here

Если вам нужен разделитель в конце представления коллекции, но есть вероятность, что вы не получите 4 ячейки в последней строке, вы можете добавить простой просмотр коллекций в виде нижнего колонтитула.

Ответ 5

Сначала вам нужно установить кросс-вставки для ячеек коллекции, после чего вам нужно программно установить фрейм для просмотра разделителя

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    return UIEdgeInsetsMake(ITEM_SPACING, ITEM_SPACING, ITEM_SPACING, ITEM_SPACING);
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UIView *seperatorView = [[UIView alloc] initWithFrame:CGRectMake(cell.frame.origin.x, cell.frame.origin.y+cell.frame.size.height, cell.frame.size.width, 2)];
    seperatorView.backgroundColor = [UIColor grayColor];
    [collectionView addSubview:seperatorView];
    [collectionView bringSubviewToFront:seperatorView];
}