最近做一个项目,要实现一个用细线分割的网格,本来以为很简单,结果发现用UICollectionView自带的布局不能满足要求,不得已去研究了一下如何自定义布局。有一些收获,和大家分享一下。先看看实现的效果图:
好了,实现自定义简单的布局实际上就是将原来在UICollectionViewDataSource,UICollectionViewDelegate中的一些布局相关的方法转移到自定义布局类中去了;只需要保留几个必须的方法,这样看起来反而层次更加清晰。
1.首先定义继承UICollectionViewLayout 的子类,这里命名为FXLayout。
实现该类时有几点需要注意:
prepareLayout方法是初始化该类时调用的方法(所以不需要实现init之类的方法,记得加上[super prepareLayout]就行了),在该方法中可以初始化一些数据。我在这里初始化了单元格的数量。
苹果提供的非常方便的接口来获取当前布局类加载的UICollectionView对象,调用[self colletionView]即可。
不多说了,上代码:
//开始时执行的方法:初始化
- (void)prepareLayout
{
[super prepareLayout];
//CGSize size = self.collectionView.frame.size;
_cellCount = [[self collectionView] numberOfItemsInSection:0];
}
//返回IUICollectionView所包含控件的大小:一般不会变
- (CGSize)collectionViewContentSize
{
CGFloat sizeHeight;
if (_cellCount%5 == 0)
{
sizeHeight = SCREEN_WIDTH*2/3*_cellCount/5;
}
else
{
sizeHeight = SCREEN_WIDTH*2/3*(_cellCount/5+1);
}
CGSize size = CGSizeMake(SCREEN_WIDTH, sizeHeight);
return size;
}
//返回CollectionView指定单元格的大小和位置
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
//创建返回对象
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
//设置各个单元格的大小
CGSize cellSize = CGSizeZero;
CGPoint center = CGPointZero;
if (indexPath.row%10 == 3 || indexPath.row%10 == 9)
{
cellSize = CGSizeMake(SCREEN_WIDTH*2/3, SCREEN_WIDTH/3);
}
else
{
cellSize = CGSizeMake(SCREEN_WIDTH/3, SCREEN_WIDTH/3);
}
switch (indexPath.row % 10) {
case 0:
center = CGPointMake(SCREEN_WIDTH/6, indexPath.row/10*SCREEN_WIDTH*4/3+SCREEN_WIDTH/6);
break;
case 1:
center = CGPointMake(SCREEN_WIDTH/2, indexPath.row/10*SCREEN_WIDTH*4/3+SCREEN_WIDTH/6);
break;
case 2:
center = CGPointMake(SCREEN_WIDTH*5/6, indexPath.row/10*SCREEN_WIDTH*4/3+SCREEN_WIDTH/6);
break;
case 3:
center = CGPointMake(SCREEN_WIDTH/3, indexPath.row/10*SCREEN_WIDTH*4/3+SCREEN_WIDTH/2);
break;
case 4:
center = CGPointMake(SCREEN_WIDTH*5/6, indexPath.row/10*SCREEN_WIDTH*4/3+SCREEN_WIDTH/2);
break;
case 5:
center = CGPointMake(SCREEN_WIDTH/6, indexPath.row/10*SCREEN_WIDTH*4/3+SCREEN_WIDTH*5/6);
break;
case 6:
center = CGPointMake(SCREEN_WIDTH/2, indexPath.row/10*SCREEN_WIDTH*4/3+SCREEN_WIDTH*5/6);
break;
case 7:
center = CGPointMake(SCREEN_WIDTH*5/6, indexPath.row/10*SCREEN_WIDTH*4/3+SCREEN_WIDTH*5/6);
break;
case 8:
center = CGPointMake(SCREEN_WIDTH/6, indexPath.row/10*SCREEN_WIDTH*4/3+SCREEN_WIDTH*7/6);
break;
case 9:
center = CGPointMake(SCREEN_WIDTH*2/3, indexPath.row/10*SCREEN_WIDTH*4/3+SCREEN_WIDTH*7/6);
break;
default:
break;
}
attributes.size = cellSize;
//定义各单元格的中心
attributes.center = center;
return attributes;
}
//返回值控制制定CGRect返回内各单元格的大小和位置
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSMutableArray *attributes = [NSMutableArray array];
//将上面方法的返回值添加到数组中
for (NSUInteger i = 0; i < _cellCount; i ++)
{
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
[attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];
}
return attributes;
}
是不是比较容易看明白,分别实现几个功能:初始化,定义网格内容大小(CGSize),指定单元格的大小和位置,还有其他一些方法在文章最后有所涉及。
2.将CollectionView的布局对象设为上面布局类。
FXLayout *flowLayout = [[FXLayout alloc]init];
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 64, 320, SCREEN_HEIGHT-64) collectionViewLayout:flowLayout];
[collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellId"];
collectionView.delegate = self;
collectionView.dataSource = self;
//collectionView.minimumZoomScale = 0.5;
collectionView.backgroundColor = COLOR(237, 237, 237);
[self.view addSubview:collectionView];
这一步很容易,记得实现UIConllectionViewDataSource和UICollectionViewDelegate两个协议就好了。3.如前面所说,还要实现一些基本方法(定义单元格数量,内容等),
//定义展示的cell数量
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return _imageArray.count;
}
//展示的Section个数
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
//定义每个cell的内容
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
//static NSString *cellId = @"cellId";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellId" forIndexPath:indexPath];
//先移除再加载
for (UIView *view in cell.contentView.subviews) {
[view removeFromSuperview];
}
cell.backgroundColor = [UIColor whiteColor];
cell.layer.borderColor = CGCOLOR(208, 208, 208);//CGCOLOR(208, 208, 208)
cell.layer.borderWidth = 0.5;
if (_titleArray.count>=1 && _imageArray.count>=1)
{
if (indexPath.row%10 == 3 || indexPath.row%10 == 9)
{
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(cell.frame.size.width/2-40, 3, 80,80)];
imageView.image = [_imageArray objectAtIndex:indexPath.row];
[cell.contentView addSubview:imageView];
UILabel *titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, cell.frame.size.height-45, cell.frame.size.width, 40)];
titleLabel.text = [_titleArray objectAtIndex:indexPath.row];
titleLabel.textColor = COLOR(102, 102, 102);
titleLabel.font = [UIFont systemFontOfSize:12];
titleLabel.numberOfLines = 0;
titleLabel.textAlignment = NSTextAlignmentCenter;
[cell.contentView addSubview:titleLabel];
}
else
{
//要不将图片和标题统一到图片?图片是方形的
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(23, 10, 60,60)];
imageView.image = [_imageArray objectAtIndex:indexPath.row];
[cell.contentView addSubview:imageView];
UILabel *titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(0,cell.frame.size.height-45, cell.frame.size.width, 40)];
titleLabel.text = [_titleArray objectAtIndex:indexPath.row];
titleLabel.textColor = COLOR(102, 102, 102);
titleLabel.font = [UIFont systemFontOfSize:12];
titleLabel.numberOfLines = 0;
titleLabel.textAlignment = NSTextAlignmentCenter;
[cell.contentView addSubview:titleLabel];
}
}
return cell;
}
//cell被选中时的方法
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"你选择了第%ld个单元格",(long)indexPath.row);
}
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath;
//单元格消失时会调用该方法
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)itemIndexPath;
以上两个方法都是在自定义布局类中完成的。
- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath;
目前就研究了这些方法,以后还有收获再分享。
转载请注明转载地址:(与众相得的博客)http://write.blog.csdn.net/postlist