UICollectionView詳解三:UICollectionViewLayout,

來源:互聯網
上載者:User

UICollectionView詳解三:UICollectionViewLayout,

上一節中,我介紹了UICollectionViewFlowLayout的使用,它主要是使用在流式布局中的,但對於某些複雜的布局,UICollectionViewFlowLayout就不起作用了。這個時候,我們可以考慮使用UICollectionViewLayout。 UICollectionViewFlowLayout是繼承自UICollectionViewLayout,並且擁有自己的流式特性。對於一些複雜的效果,我們完全可以自訂UICollectionViewLayout來實現。

這一節,我就介紹使用UICollectionViewLayout來實現不同布局的來回切換。最終如下:

樣式1:



樣式2:



我們可以通過點擊螢幕的空白地區來回的切換上面兩種效果,並且切換過程中,動畫效果非常的流暢。

主介面的代碼和以前一樣,設定資料來源;初始化UICollectionView;註冊UICollectionViewCell;代碼如下:

@interface ViewController ()<UICollectionViewDataSource,UICollectionViewDelegate>@property (nonatomic,strong) NSMutableArray *images;@property (nonatomic,weak) UICollectionView *collectionView;@endstatic NSString *const identifer = @"ImageCell";@implementation ViewController-(NSMutableArray *)images {    if (!_images) {        _images = [NSMutableArray array];        for (int i=1;i<=8;i++) {            [_images addObject:[NSString stringWithFormat:@"%d.jpg",i]];        }    }    return _images;}- (void)viewDidLoad {    [super viewDidLoad];        CGRect rect = CGRectMake(0, 150, self.view.frame.size.width,400);    UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:rect collectionViewLayout:[[LFStackLayout alloc] init]];    collectionView.dataSource = self;    collectionView.delegate = self;        // 註冊collectionView(因為是從xib中載入cell的,所以registerNib)    [collectionView registerNib:[UINib nibWithNibName:@"ImageCell" bundle:nil] forCellWithReuseIdentifier:identifer];        [self.view addSubview:collectionView];        self.collectionView = collectionView;}#pragma mark - 點擊螢幕空白處,切換配置模式- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {    if ([self.collectionView.collectionViewLayout isKindOfClass:[LFStackLayout class]]) {        [self.collectionView setCollectionViewLayout:[[LFCircleLayout alloc] init] animated:YES];    } else {        [self.collectionView setCollectionViewLayout:[[LFStackLayout alloc] init] animated:YES];    }}#pragma mark - delegate- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {    return  self.images.count;}- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {        ImageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifer forIndexPath:indexPath];        cell.iconName = self.images[indexPath.item];        return cell;}- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {    // 1. 刪除模型資料    [self.images removeObjectAtIndex:indexPath.item];        // 2. 刪除UI元素    [collectionView deleteItemsAtIndexPaths:@[indexPath]];}

關鍵代碼就是這一段,用來實現“堆疊布局”和“圓形布局”的自由切換。

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {    if ([self.collectionView.collectionViewLayout isKindOfClass:[LFStackLayout class]]) {        [self.collectionView setCollectionViewLayout:[[LFCircleLayout alloc] init] animated:YES];    } else {        [self.collectionView setCollectionViewLayout:[[LFStackLayout alloc] init] animated:YES];    }}

這裡,我就“圓形布局”進行說明,自訂LFCircleLayout, 並且繼承自UICollectionViewLayout

@interface LFCircleLayout : UICollectionViewLayout@end

UICollectionViewFlowLayout是可以直接擷取到所有Item的FlowLayout,然後對各自的layout進行調整;而UICollectionViewLayout完全需要自訂,來滿足自己的需求。主要是下面的代碼,重寫父類的 layoutAttributesForElementsInRect方法,返回的數組對象就是自訂layout的集合。當擷取到這個集合後,UICollectionView就會對每一個Item進行自動調節。
-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {     ...}

自訂LFCircleLayout中實現的layoutAttributesForElementsInRect方法如下:

-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {    NSMutableArray *array = [NSMutableArray array];    NSInteger count = [self.collectionView numberOfItemsInSection:0];        for (int i=0; i<count; i++) {        UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];        [array addObject:attrs];    }        return array;}

代碼中定義了一個方法:layoutAttributesForItemAtIndexPath, 專門用來設定每個Item的layout,完成“圓形布局”。代碼如下:

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {    UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];    attrs.size = CGSizeMake(60, 60);        // 第幾個Item    NSInteger index = indexPath.item;        // 半徑100    CGFloat radius = 100;        // 圓心    CGFloat circleX = self.collectionView.frame.size.width * 0.5;    CGFloat circleY = self.collectionView.frame.size.height * 0.5;        NSInteger count = [self.collectionView numberOfItemsInSection:0];    CGFloat singleItemAngle = 360.0 / count;        // 計算各個環繞的圖片center    attrs.center = CGPointMake(circleX + radius * cosf(kCalcAngle(singleItemAngle * index)), circleY - radius * sinf(kCalcAngle(singleItemAngle * index)));        return attrs;}

代碼中關於計算弧度的方法,我定義了一個宏來處理。

#define kCalcAngle(x) x * M_PI / 180.0

“堆疊布局”我就不做介紹了,基本類似,主要代碼如下:

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {    UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];    attrs.size = CGSizeMake(150, 150);    attrs.center = CGPointMake(self.collectionView.frame.size.width * 0.5, self.collectionView.frame.size.height * 0.5);        NSInteger index = indexPath.item;    CGFloat angles[] ={0,15,30,45,60};    NSInteger count = [self.collectionView numberOfItemsInSection:0];        if (index >= 5) {        attrs.hidden = YES;    } else {        attrs.transform = CGAffineTransformMakeRotation(kCalcAngle(angles[index]));        attrs.zIndex = count - index;    }        return attrs;}-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {    NSMutableArray *array = [NSMutableArray array];    NSInteger count = [self.collectionView numberOfItemsInSection:0];        for (int i=0; i<count; i++) {        UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];        [array addObject:attrs];    }        return array;}


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.