How to display 3 cell per row UICollectionView

2019-03-05 10:37发布

问题:

As per the header, I'm using UICollectionView to display images. I need to display 3 cells per row, something like how Instagram does it.

Because there are many screen sizes, I'm getting the width of the iPhone screen, then divide it by 3. However, it does not show as per what I need it to be.

Here are my codes inside the viewDidLoad() method:

private let leftAndRightPaddings: CGFloat = 8.0
private let numberOfItemsPerRow: CGFloat = 3.0
private let heightAdjustment: CGFloat = 30.0    

let bounds = UIScreen.mainScreen().bounds
let width = (bounds.size.width - leftAndRightPaddings) / numberOfItemsPerRow
let layout = userDetailCollection.collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSizeMake(width, width)

回答1:

Replace this line

let width = (bounds.size.width - leftAndRightPaddings) / numberOfItemsPerRow

with

let width = (bounds.size.width - leftAndRightPaddings*4) / numberOfItemsPerRow

As you are not considering spacing between two items & Right insets spacing therefore it is not adjusting in the screen.

private let leftAndRightPaddings: CGFloat = 15.0
private let numberOfItemsPerRow: CGFloat = 3.0

let bounds = UIScreen.mainScreen().bounds
let width = (bounds.size.width - leftAndRightPaddings*(numberOfItemsPerRow+1)) / numberOfItemsPerRow
let layout = userDetailCollection.collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSizeMake(width, width)   

Try this code



回答2:

overriding UICollectionViewLayout will let you much more flexibility in creating collectionViews. here is a snippet for YourOwnCollectionViewLayout : UICollectionViewLayout:

- (NSInteger)itemWidth {
    return (self.collectionView.bounds.size.width - (HORIZONTAL_PAD * (NUMBER_OF_ITEMS_PER_ROW+1))) / NUMBER_OF_ITEMS_PER_ROW; // pad from each side + pad in the middle
}

- (NSInteger)itemHeight {
    return self.itemWidth; // or something else
}

- (NSString *)keyForIndexPath:(NSIndexPath *)indexPath {
    NSString *retVal = [NSString stringWithFormat:@"%ld-%ld", (long)indexPath.section, (long)indexPath.row];
    return retVal;
}

- (CGRect)frameForItemAtIndexPath:(NSIndexPath *)indexPath {
    CGFloat itemWidth  = [self itemWidth];
    CGFloat itemHeight = [self itemHeight];

    CGFloat originX = HORIZONTAL_PAD + ((indexPath.row % NUMBER_OF_ITEMS_PER_ROW)*(HORIZONTAL_PAD + itemWidth));
    CGFloat originY = VERTICAL_PAD + (floorf(indexPath.row/NUMBER_OF_ITEMS_PER_ROW)*(VERTICAL_PAD + itemHeight));

    return CGRectMake(originX, originY, itemWidth, itemHeight);
}

- (void)prepareLayout {
    NSMutableDictionary *newLayoutInfo  = [NSMutableDictionary dictionary];
    NSMutableDictionary *cellLayoutInfo = [NSMutableDictionary dictionary];

    NSInteger sectionCount = [self.collectionView numberOfSections];
    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0];

    for (NSInteger section = 0; section < sectionCount; section++) {
        NSInteger itemCount = [self.collectionView numberOfItemsInSection:section];

        for (NSInteger item = 0; item < itemCount; item++) {
            indexPath = [NSIndexPath indexPathForItem:item inSection:section];

            UICollectionViewLayoutAttributes *itemAttributes =
            [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
            itemAttributes.frame = [self frameForItemAtIndexPath:indexPath];

            NSString *key        = [self keyForIndexPath:indexPath];
            cellLayoutInfo[key]  = itemAttributes;
        }
    }

    newLayoutInfo[@"CellKind"] = cellLayoutInfo;
    self.layoutInfo            = newLayoutInfo;
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
    NSString *key = [self keyForIndexPath:indexPath];
    UICollectionViewLayoutAttributes *retVal = self.layoutInfo[@"CellKind"][key];
    return retVal;
}

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
    NSMutableArray *allAttributes = [NSMutableArray arrayWithCapacity:self.layoutInfo.count];

    [self.layoutInfo enumerateKeysAndObjectsUsingBlock:^(NSString *elementIdentifier,
                                                         NSDictionary *elementsInfo,
                                                         BOOL *stop) {
        [elementsInfo enumerateKeysAndObjectsUsingBlock:^(NSIndexPath *indexPath,
                                                          UICollectionViewLayoutAttributes *attributes,
                                                          BOOL *innerStop) {

            if (CGRectIntersectsRect(rect, attributes.frame)) {
                [allAttributes addObject:attributes];
            }
        }];
    }];

    return allAttributes;
}

- (CGSize)collectionViewContentSize {
    return CGSizeMake(self.collectionView.bounds.size.width, floorf([self.collectionView numberOfItemsInSection:0]/NUMBER_OF_ITEMS_PER_ROW) * (self.itemHeight + VERTICAL_PAD) + VERTICAL_PAD);
}

in your mainView add: [[UICollectionView alloc] initWithFrame:self.bounds collectionViewLayout:[[YourOwnCollectionViewLayout alloc] init]]; and you're DONE!



回答3:

You are not considering the sectionInset and the interItemSpacing. It has some default values which pushes the cells(gives padding). Either you can set the interItemSpacing to 0 and sectionInset to UIEdgeInsetsZero or you have to consider their values during calculation of the cellWidth.

Override these protocol methods for setting the size, insets and interItem spacing

optional public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize

optional public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets

optional public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat

optional public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat