web-dev-qa-db-ja.com

UICollectionViewのUICollectionViewCells間にビューを追加するにはどうすればよいですか?

UIViewUICollectionViewCellsの間にUICollectionViewsを追加しようとしていますが、どうすればよいかわかりません。私はこのようなことを達成しようとしています:

Screenshot

おそらくカスタムのUICollectionViewLayoutを作成する必要がありますが、どこから始めればよいのかよくわかりません。

24
Marco Pompei

UICollectionViewLayoutsがどのように機能するかをさらに研究し、それを解決する方法を見つけました。レイアウトを処理する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

46
Marco Pompei

CollectionViewの背景が緑でcontentViewが白の場合、セル間にスペースを入れて水平線を取得できるように見えます minimumLineSpacing 。垂直方向のギャップは注意が必要ですが、contentViewを工夫して、 minimumInteritemSpacing を慎重に設定すると、それを取得できます。

0
Samuel

セクションを使用していて、それに適したレイアウトの場合は、セクションのヘッダーとフッターを使用できます。

しかし、あなたの図に基づくと、これらのビューを含むように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;
}
0