【iOS】UICollectionView

文章目录

前言

UICollectionView是iOS开发中一种功能强大的视图容器,用于展示可滚动且布局灵活多样的内容集合,它能以网格、流水等多种形式呈现数据元素,像展示图片集、商品列表等场景都很适用。开发者可借助相关布局类(如UICollectionViewFlowLayout等)以及遵循对应代理协议,来定制单元格外观、尺寸、间距等布局细节,从而打造出符合不同需求的美观且实用的界面效果。

实现九宫格布局

这里实现一个九宫格布局来简单的使用一下UICollectionView,实现的步骤很简单:

  • 创建布局类为其各个属性赋值。
  • 将其传递给UICollectionView的初始化方法:\- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout NS_DESIGNATED_INITIALIZER;
  • 设置代理,实现相关方法。

实现代码:

objective-c 复制代码
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    
    UICollectionViewFlowLayout* layout = [[UICollectionViewFlowLayout alloc] init];
    //设置一个垂直流布局
    layout.scrollDirection = UICollectionViewScrollDirectionVertical;
    //设置每个item的大小是100*100
    layout.itemSize = CGSizeMake(100, 100);
    layout.minimumInteritemSpacing = 10;
    
    _collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
    _collectionView.delegate = self;
    _collectionView.dataSource = self;
    
    [_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellid"];
    
    [self.view addSubview: _collectionView];
    
}

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    return 1;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return 101;
}

- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell* cell = [_collectionView dequeueReusableCellWithReuseIdentifier:@"cellid" forIndexPath:indexPath];
    cell.backgroundColor = [UIColor colorWithRed: arc4random() % 255 / 255.0 green: arc4random() % 255 / 255.0 blue: arc4random() % 255 / 255.0 alpha: 1.0];
   
    return cell;
}
@end

layout中常用的一些属性

itemSize:设置item的大小。

minimumLineSpacing:设置item每一行之间的间距。

minimumInteritemSpacing:设置每行中item之间的间距。这里需要注意的是,系统通过minimumInteritemSpacing属性计算一行可以放多少个item,当发现放不下计算好的item个数时,为了撑满所在行,此值就会变大

scrollDirection:设置滚动的方向。

UICollectionView有两种布局方法分别为水平流和垂直流,简单来说就是,一个是竖屏滚动,一个是横屏滚动,在笔者的学习过程中笔者均使用的是垂直流布局。

sectionInset:设置分区之间的间距。

在设置item大小的时候,我们可以使用协议中的方法让item的大小不同:

objective-c 复制代码
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.item % 2) {
        return CGSizeMake((self.view.bounds.size.width - 12) / 3, (self.view.bounds.size.width - 12) / 3);
    } else {
        return CGSizeMake((self.view.bounds.size.width - 12) / 6, (self.view.bounds.size.width - 12) / 6);
    }
}

效果图

参差瀑布流的实现

我们要实现一个参差效果的瀑布流时就需要我们使用UICollectionViewFlowLayout的自定义子类来实现,由于item的高度不一,故而原来OC提供的无法实现这个效果。

声明自定义子类

Mylayout.h

objective-c 复制代码
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface Mylayout : UICollectionViewFlowLayout
@property (nonatomic, copy) NSMutableArray* attributaArray;
@property (nonatomic, copy) NSMutableArray* columnHeight;
@property (nonatomic, assign) NSInteger itemCount;
@end

NS_ASSUME_NONNULL_END

Mylaout.m:

objective-c 复制代码
#import "Mylayout.h"

@implementation Mylayout

- (void)prepareLayout {
    _attributaArray = [NSMutableArray array];
    [super prepareLayout];
    
    CGFloat cellWidth = ([UIScreen mainScreen].bounds.size.width - self.sectionInset.right - self.sectionInset.left - self.minimumInteritemSpacing) / 2;
        _columnHeight = [NSMutableArray arrayWithObjects:@(self.sectionInset.top), @(self.sectionInset.top), nil];
    for(int i = 0; i < _itemCount; i++) {
        NSIndexPath* index = [NSIndexPath indexPathForRow:i inSection:0];
        UICollectionViewLayoutAttributes* attribute = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:index];
        CGFloat height = arc4random() % 200 + 50;
        NSInteger minLine = [_columnHeight[0] doubleValue] < [_columnHeight[1] doubleValue] ? 0 : 1;
        _columnHeight[minLine] = @([_columnHeight[minLine] doubleValue] + self.minimumLineSpacing + height);
        
        attribute.frame = CGRectMake(self.sectionInset.left + (self.minimumInteritemSpacing + cellWidth) * minLine,[_columnHeight[minLine] doubleValue] - height - self.minimumLineSpacing,cellWidth, height);

        [_attributaArray addObject:attribute];
    }
}

- (NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
    return _attributaArray;
}

- (CGSize)collectionViewContentSize {
    CGFloat fristHeight = [_columnHeight[0] doubleValue];
    CGFloat secondHeight = [_columnHeight[1] doubleValue];
    CGFloat maxHeight = fristHeight > secondHeight ? fristHeight : secondHeight;
    return CGSizeMake(0, maxHeight);
}

@end

这里我们在设置自定义子类的时候,我们必须要实现以下几个方法:

objective-c 复制代码
- (void)prepareLayout;//提前进行布局
- (NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;//返回所有元素的布局属性,一般情况下返回的是一个数组
- (CGSize)collectionViewContentSize;//设置画布大小
相关推荐
阿祖zu8 小时前
芝士就是力量!开源私有化部署与 GitHub 双向同步的个人知识笔记 App
前端·后端·ios
GitLqr14 小时前
iOS 27 强制要求 UISceneDelegate:UIKit 和 Flutter 开发者该如何应对?
flutter·ios·全栈
MoSTChillax14 小时前
数字人竞品分析(中):核心功能、产品使用与技术能力对比
ide·macos·xcode
屑曦晨17 小时前
PKToolPicker工具栏图标错误模糊问题排查报告
ios
2501_9159214318 小时前
详细解析,iOS 应用上架 App Store 的完整流程与指南
android·ios·小程序·https·uni-app·iphone·webview
2501_9151063218 小时前
SwiftUI项目创建详解:使用Xcode从零开始创建第一个App项目
ide·vscode·ios·swiftui·个人开发·xcode·敏捷流程
2501_9159184118 小时前
Xcode调试iOS应用内存管理与优化,识别泄漏与性能监控指南
android·ios·小程序·uni-app·cocoa·iphone·xcode
97650333520 小时前
iOS 上架/审核 4.3a Cocos 2026最新方案解读
flutter·ios·swift·cocos2d·ios开发
2501_9160074720 小时前
IDE 是什么?集成开发环境详解与 iOS 开发选型指南
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
梦想的颜色20 小时前
UniApp 四端对齐实战:iOS App / Android App / 小程序 / H5 兼容坑点与完整解决方案|AI 辅助多端落地
android·ios·小程序·uni‑app·uniapp 四端适配·多端兼容·ai 生成 uni‑app