最近做一个项目,要实现一个用细线分割的网格,本来以为很简单,结果发现用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); } 4.上面的方法能满足基本的显示网格的需求,但是其他方面还缺失一些。下面是一些扩展内容:
//单元格显示时会调用该方法,可以完成一些动画
- (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 |
|
来自: 叹落花 > 《collectionView》