美文网首页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