美文网首页iOS技术栈
UICollectionViewLayout之CircleLay

UICollectionViewLayout之CircleLay

作者: 月咏蝴蝶 | 来源:发表于2016-03-17 14:43 被阅读471次

之前使用UICollectionView只把它当成UITableView的加强版来使用,并不特别理解原来UICollectionViewLayout有着挺强大的功能,在这里模仿一下网上的源码,写一份让自己印象更加深刻。

UICollectionViewLayout 实现 CircleLayout

在这里,我使用的是XIB实现UICollectionView。

这里是ViewController里面的viewDidLoad()

    // Add Gesture
    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
    [self.circleCV addGestureRecognizer:tapGesture];

    // 设置 UICollectionViewLayout
    self.circleCV.collectionViewLayout = [[CircleLayout alloc] init];
    
    // Register UICollectionViewCell
    UINib *circleNib = [UINib nibWithNibName:@"CircleCollectionViewCell" bundle:[NSBundle mainBundle]];
    [self.circleCV registerNib:circleNib forCellWithReuseIdentifier:@"CELL"];
    [self.circleCV registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:@"FirstSupplementary" withReuseIdentifier:@"ReuseID"];
    [self.circleCV registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:@"SecondSupplementary" withReuseIdentifier:@"ReuseID"];

在这里只用实现 UICollectionViewDataSource

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
    return self.cellCount;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    CircleCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CELL" forIndexPath:indexPath];
    return cell;
}

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    UICollectionReusableView *view = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"ReuseID" forIndexPath:indexPath];
    view.backgroundColor = [UIColor greenColor];
    UILabel *label = [[UILabel alloc] init];
    label.text = kind;
    label.font = [UIFont systemFontOfSize:24];
    [label sizeToFit];
    label.center = CGPointMake(view.bounds.size.width/2, view.bounds.size.height/2);
    [view addSubview:label];
    
    return view;
}

UICollectionViewCell只是一个50X50的UIImageView,在这里我就不贴上来了。

UICollectionView有三个部分构成

  • Cells
  • Supplementary Views 追加视图 (类似Header或者Footer)
  • Decoration Views 装饰视图 (用作背景展示)

下一步我们需要建立一个继承于UICollectionViewLayout的子类
每一个layout都需要实现以下方法:

- collectionViewContentSize
- shouldInvalidateLayoutForBoundsChange:
- layoutAttributesForElementsInRect:
- layoutAttributesForItemAtIndexPath:
- layoutAttributesForSupplementaryViewOfKind:atIndexPath: (如果layout 支持 supplementary views)
- layoutAttributesForDecorationViewWithReuseIdentifier:atIndexPath: (如果layout 支持 decoration views)

当UICollectionView发生数据改变的时候,比如插入和删除,需要实现以下方法:

- initialLayoutAttributesForInsertedItemAtIndexPath:
- initialLayoutAttributesForInsertedSupplementaryElementOfKind:atIndexPath:
- finalLayoutAttributesForDeletedItemAtIndexPath:
- finalLayoutAttributesForDeletedSupplementaryElementOfKind:atIndexPath:

实现代码:

- (void)prepareLayout{
    [super prepareLayout];
    
    [self registerClass:[CollectionReusableView class] forDecorationViewOfKind:@"MyDecoration"];
    
    self.size = self.collectionView.frame.size;
    self.cellCount = [[self collectionView] numberOfItemsInSection:0];
    self.center = CGPointMake(self.size.width / 2.0, self.size.height / 2.0);
    self.radius = MIN(self.size.width, self.size.height) / 2.5;
}

- (CGSize)collectionViewContentSize{
    return [self collectionView].frame.size;
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
    UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    attributes.size = CGSizeMake(50, 50);
    attributes.center = CGPointMake(self.center.x + self.radius * cosf(2*indexPath.item*M_PI/self.cellCount), self.center.y + self.radius * sinf(2*indexPath.item*M_PI/self.cellCount));
    return attributes;
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath{
    UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:elementKind withIndexPath:indexPath];
    
    attributes.size = CGSizeMake(260, 40);
    if([elementKind isEqual:@"FirstSupplementary"]){
        attributes.center = CGPointMake(self.size.width/2, 40);
    }
    else{
        attributes.center = CGPointMake(self.size.width/2, self.size.height-40);
    }
    return attributes;
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath{
    UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:elementKind withIndexPath:indexPath];
    
    attributes.size = CGSizeMake(140, 40);
    attributes.center = CGPointMake(self.size.width/2, self.size.height/2);
    
    return attributes;
}

- (NSArray*)layoutAttributesForElementsInRect:(CGRect)rect{
    NSMutableArray* array = [NSMutableArray array];
    for (NSInteger i=0 ; i < self.cellCount; i++) {
        NSIndexPath* indexPath = [NSIndexPath indexPathForItem:i inSection:0];
        [array addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];
    }
    
    //add first supplementaryView
    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0];
    UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForSupplementaryViewOfKind:@"FirstSupplementary" atIndexPath:indexPath];
    [array addObject:attributes];
    
    //add second supplementaryView
    attributes = [self layoutAttributesForSupplementaryViewOfKind:@"SecondSupplementary" atIndexPath:indexPath];
    [array addObject:attributes];
    
    //add decorationView
    attributes = [self layoutAttributesForDecorationViewOfKind:@"MyDecoration" atIndexPath:indexPath];
    [array addObject:attributes];
    return array;
}

- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForInsertedItemAtIndexPath:(NSIndexPath *)itemIndexPath{
    UICollectionViewLayoutAttributes* attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];
    attributes.alpha = 0.0;
    attributes.center = CGPointMake(self.center.x, self.center.y);
    return attributes;
}

- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDeletedItemAtIndexPath:(NSIndexPath *)itemIndexPath{
    UICollectionViewLayoutAttributes* attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];
    attributes.alpha = 0.0;
    attributes.center = CGPointMake(self.center.x, self.center.y);
    attributes.transform3D = CATransform3DMakeScale(0.1, 0.1, 1.0);
    return attributes;
}

最后放上实现效果图:

C7BC8853-ECCE-436D-B4C7-451318BD7EEC.png

相关文章

网友评论

本文标题:UICollectionViewLayout之CircleLay

本文链接:https://www.haomeiwen.com/subject/rjrclttx.html