答案 0 :(得分:5)
您应该 2个部分。
第1节有3个单元格
第2节有2个单元格
然后您可以 adjust the inset 与collectionView(_:layout:insetForSectionAt:)
一起使用您要调整的部分。 (在这种情况下,第2节)
如果未实现此方法,则流布局将使用值 其部分Inset属性用于设置边距。您的 此方法的实现可以返回一组固定的边距大小 或者为每个部分返回不同的边距大小。
部分插入是 边距仅适用于该部分中的项目。他们代表了 标题视图与第一行项目之间的距离和 在最后一行项目和页脚视图之间。他们还表示 它们在一行物品的两侧间隔开。他们不 影响页眉或页脚本身的大小。
为第2部分项创建自定义子类,您可以在其中自定义UICollectionViewCell
contentView
子视图的实际内容的插入内容。
然后在第2部分中,返回您的自定义单元格。
答案 1 :(得分:4)
答案 2 :(得分:2)
您可以通过将部分数量从1更改为2来在UICollectionView中实现此类型的格式。
然后,您可以相应地为不同的部分定义自定义UICollectionViewFlowLayout。
答案 3 :(得分:2)
解决方案:我创建了一个名为“CenteringCollectionView”的UICollectionView子类,并对我制作的部分进行了一些计算!
.h文件:
#import <UIKit/UIKit.h>
@class CenteringCollectionView;
@protocol CenteringCollectionViewDelegate <NSObject>
-(void)collectionView:(CenteringCollectionView *)collectionView didDequeueReusableCell:(UICollectionViewCell *)cell indexPath:(NSIndexPath *)indexPath;
@end
@interface CenteringCollectionView : UICollectionView
@property (nonatomic, strong) NSMutableArray *dataSourceArr;
@property (nonatomic, weak) id<CenteringCollectionViewDelegate> delegateCenteringCollection;
@end
.m文件:
#import "CenteringCollectionView.h"
@interface CenteringCollectionView () <UICollectionViewDelegate, UICollectionViewDataSource>
@property (nonatomic, assign) IBInspectable long elementsInRow;
@property (nonatomic, assign) long elementsInRowInitialValue;
@property (nonatomic) IBInspectable NSString *cellIdentifier;
@property (nonatomic) IBInspectable CGFloat cellRelativeSize; // 0..1
@property (nonatomic, assign) long numOfSections;
@property (nonatomic, assign) IBInspectable BOOL autoResize; // *** If we want auto resize - we need to set the height constraint of the collection view in size of 1 line only even if we have more than 1 line (section).
@property (nonatomic, assign)IBInspectable CGFloat heightMiddleSpacing;
@property (nonatomic, assign) long cellSize;
//@property (nonatomic, assign) CGFloat verticalTopInset;
@property (nonatomic, assign) CGFloat initialHeightConstraint;
@property (nonatomic, weak) NSLayoutConstraint *selfHeightConstraint;
@property (nonatomic, assign) CGFloat cellSpacing;
@property (nonatomic, assign) BOOL shouldReloadUIElements;
// UI IBInspectable
@property (nonatomic, weak) IBInspectable UIColor *runtimeColor;
@end
static long const maxElementsInRowDefault = 3;
@implementation CenteringCollectionView
-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder])
{
self.elementsInRow = maxElementsInRowDefault; // will get the default value if not stored value in storyboard
self.elementsInRowInitialValue = self.elementsInRow;
self.cellRelativeSize = 0.5;
self.initialHeightConstraint = -1;
}
return self;
}
-(void)setDataSourceCount:(long)dataSourceCount
{
if (dataSourceCount == _dataSourceCount)
{
return;
}
_dataSourceCount = dataSourceCount;
self.shouldReloadUIElements = YES;
self.elementsInRow = MIN(self.elementsInRowInitialValue, self.dataSourceCount);
self.numOfSections = ceil((CGFloat)self.dataSourceCount / (CGFloat)self.elementsInRow);
CGFloat selfHeight = [self handleAutoResizeAndReturnTheNewHeightIfNeeded];
CGFloat selfWidth = CGRectGetWidth(self.frame);
CGFloat cellWidth = (selfWidth / self.elementsInRow) * self.cellRelativeSize;
CGFloat cellHeight = (selfHeight / self.numOfSections) * self.cellRelativeSize;
self.cellSize = MIN(cellWidth, cellHeight);
dispatch_async(dispatch_get_main_queue(), ^{
[self setCollectionView];
[self reloadData];
});
}
-(void)awakeFromNib
{
[super awakeFromNib];
self.elementsInRowInitialValue = self.elementsInRow;
[self handleUIelementsIBInspectable];
}
-(void)handleUIelementsIBInspectable
{
if (self.runtimeColor)
{
[self setBackgroundColor:self.runtimeColor];
}
}
-(CGFloat)handleAutoResizeAndReturnTheNewHeightIfNeeded
{
if (self.autoResize)
{
for (NSLayoutConstraint *constraint in [self constraints])
{
if (constraint.firstAttribute == NSLayoutAttributeHeight)
{
if (self.initialHeightConstraint == -1) // not set yet
{
self.initialHeightConstraint = constraint.constant;
}
if (!self.selfHeightConstraint)
{
self.selfHeightConstraint = constraint;
}
CGFloat newHeight = self.initialHeightConstraint * self.numOfSections;
constraint.constant = newHeight;
if (self.bounds.size.height != newHeight)
{
CGRect frame = self.bounds;
frame.size.height = newHeight;
[self setBounds:frame];
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.superview layoutIfNeeded];
[self layoutIfNeeded];
});
return newHeight;
}
}
}
return CGRectGetHeight(self.frame);
}
-(long)numOfSpacesInRow
{
return self.elementsInRow + 1;
}
-(long)numOfSpacesBetweenLines
{
return self.numOfSections + 1;
}
-(void)setCellRelativeSize:(CGFloat)cellRelativeSize
{
_cellRelativeSize = MAX(0, MIN(cellRelativeSize, 1));
}
-(void)setCollectionView
{
[self reloadData];
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
CGFloat horizontalCellSpacing = ((CGRectGetWidth(self.frame) - (self.cellSize * self.elementsInRow)) / self.numOfSpacesInRow);
CGFloat verticalCellSpacing = (CGRectGetHeight(self.frame) - (self.numOfSections * self.cellSize)) / self.numOfSpacesBetweenLines;
self.cellSpacing = MAX(MIN(horizontalCellSpacing, verticalCellSpacing), 0);
[layout setMinimumInteritemSpacing:self.cellSpacing];
[layout setMinimumLineSpacing:self.cellSpacing];
[layout setScrollDirection:UICollectionViewScrollDirectionVertical];
[self setCollectionViewLayout:layout];
self.showsVerticalScrollIndicator = NO;
self.showsHorizontalScrollIndicator = NO;
self.scrollEnabled = NO;
if (!self.delegate)
{
self.delegate = self;
self.dataSource = self;
}
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(self.cellSize, self.cellSize);
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
BOOL isLastSection = (section == self.numOfSections - 1);
if (isLastSection == NO)
{
return self.elementsInRow;
}
else
{
long numOfLeftItemsInLastRow = self.dataSourceCount % self.elementsInRow;
if (numOfLeftItemsInLastRow == 0)
{
return self.elementsInRow;
}
else
{
return numOfLeftItemsInLastRow;
}
}
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:self.cellIdentifier forIndexPath:indexPath];
if ([self.delegateCenteringCollection respondsToSelector:@selector(collectionView:didDequeueReusableCell:indexPath:)])
{
[self.delegateCenteringCollection collectionView:self didDequeueReusableCell:cell indexPath:[self indexPathWithoutSectionsFrom:indexPath]];
}
return cell;
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
if ([self.delegateCenteringCollection respondsToSelector:@selector(collectionView:didSelectItemAtIndexPath:cell:)])
{
UICollectionViewCell *selectedCell = [collectionView cellForItemAtIndexPath:indexPath];
[self.delegateCenteringCollection collectionView:self didSelectItemAtIndexPath:[self indexPathWithoutSectionsFrom:indexPath] cell:selectedCell];
}
}
-(NSIndexPath *)indexPathWithoutSectionsFrom:(NSIndexPath *)indexPath
{
long sectionNum = indexPath.section;
long rowNum = sectionNum * self.elementsInRow + indexPath.row;
NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:rowNum inSection:0];
return newIndexPath;
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return self.numOfSections;
}
-(void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
{
dispatch_async(dispatch_get_main_queue(), ^{
if (self.shouldReloadUIElements == NO)
{
return;
}
if (self.autoResize && self.selfHeightConstraint)
{
BOOL isTheFirstCellInTheLastSection = (indexPath.section == self.numOfSections - 1) && indexPath.row == 0;
if (isTheFirstCellInTheLastSection)
{
CGFloat newHeight = CGRectGetMaxY(cell.frame) + self.cellSpacing;
self.selfHeightConstraint.constant = newHeight;
if (self.bounds.size.height != newHeight)
{
CGRect frame = self.bounds;
frame.size.height = newHeight;
[self setBounds:frame];
}
[self.superview layoutIfNeeded];
[self layoutIfNeeded];
}
}
});
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
if (self.shouldReloadUIElements == NO)
{
return collectionView.contentInset;
}
NSInteger cellsCount = [collectionView numberOfItemsInSection:section];
CGFloat horizontalInset = (collectionView.bounds.size.width - (cellsCount * self.cellSize) - ((cellsCount - 1) * self.cellSpacing)) * 0.5;
horizontalInset = MAX(horizontalInset, 0.0);
BOOL isLastSection = (section == self.numOfSections - 1);
CGFloat verticalTopInset = self.cellSpacing;
CGFloat verticalBottomInset = verticalTopInset;
if (section == 0 && isLastSection == NO)
{
if (self.heightMiddleSpacing)
{
verticalBottomInset += self.heightMiddleSpacing;
}
verticalBottomInset /= 2;
}
if (section > 0)
{
if (self.heightMiddleSpacing)
{
verticalTopInset += self.heightMiddleSpacing;
}
verticalTopInset /= 2;
if (isLastSection == NO)
{
if (self.heightMiddleSpacing)
{
verticalBottomInset += self.heightMiddleSpacing;
}
verticalBottomInset /= 2;
}
}
return UIEdgeInsetsMake(verticalTopInset, horizontalInset, verticalBottomInset, horizontalInset);
}
@end
为了使其有效,我们在父视图中需要做的就是:
self.collectionView.delegateCenteringCollection = self;
self.collectionView.dataSourceCount = 5; // Or whatever number we want!
在故事板中:我们需要创建此类的collectionView并设置“行中的元素”值,同时将“单元格标识符”和“单元格相对大小”设置为0到1之间(“单元格相对大小”值:将根据collectionView width&amp; height)计算单元格大小和填充。 最后 - 如果您希望集合视图根据行数自动调整其自身的高度约束(如果存在),则将“autoResize”设置为“true”。如果我们将“autoResize”设置为true,我们设置为collectionView的高度约束将确定单个行的高度。如果我们的collectionView应该增长到例如3行,它将使我们的collectionview高度约束加倍3。
它就像一个魅力!