使用UICollectionView自定义样式01,的灵活使用

2020-03-24 11:11 来源:未知

UICollectionView 是 iOS6 推出的 API, 能够完结复杂的定制效果, 使用和 UITableView 相似, 那篇主要透过自定义 UICollectionViewFlowLayout 落成多个左右滑动, 扶持加大的相册效果

UICollectionViewFlowLayout是系统提必要我们贰个装进好的流布局划虚构置类,它的父类是UICollectionViewLayout,相对于父类它抱有部分非常的属性。

最新的急需中,要求落到实处一个显得国粹上新的视图,表现格局是点击叁个UITableView的cell,在cell拉出一个空手的“抽屉”视图,“抽屉”中横向体现可滚动的多个至宝的图像和文字视图,于是很自然地想到用UICollectionView来兑现。后来那么些供给被砍掉了(orz),但是UICollectionView是三个很风趣很灵活的视图,形似Android的GridView,不过比之功能越来越强有力,它能够切切实实到每二个item的定制,完全决议于UICollectionViewLayout的完成。

1.亲信大家都会很熟悉运用UITableView了,然而前些天给我们介绍三个iOS6就曾经引进的UICollectionView ,功效更抓牢大,更灵敏,学会运用它,会 帮您化解超多的主题素材的!它跟UITableView很相同,所以 熟知使用UICollectionView很简短!

美高梅网投网址 1003.png

美高梅网投网址 2UICollectionViewFlowLayout的属性

answer huang的译文中如此表达UICollectionView:

2 。先列举三个轻巧的事例

  • 能够滚动, 必定世襲自 UIScrollView
  • 数据量未知, 为了防止内存过大引致 crash, 由此必要动用全数循环使用机制的控件, 不然还亟需自写一套循环利机制
  • UITableView 也可完毕, 不过相比较奇葩 (必要将全体 tableView 90 °, cell 内容旋转 90 °卡塔尔
  • 自定义 UICollectionViewLayout 完全能够满足急需, 并实现一套完全能够复用的构造方案
  • 可继续自 UICollectionView 提供 的 UICollectionViewFlowLayout, 并在这里幼功上做更动

上边依次批注各个属性:

UITableView和UICollectionView都以由data-source和delegate驱动的。他们为其出示的子视图册扮演为愚笨的器皿(dumb containers卡塔尔国,对她们愚直的内容(contents)毫不知情。

美高梅网投网址 3

UICollectionViewLayout 提供了以下 API 调控自定义构造的样式, 实现定制效果

1、设置行与行以内的区间最小间隔

UICollectionView进一层抽象了。它将其子视图的职位,大小和外观的调控权委托给八个独自的布局对象。通过提供几个自定义结构对象,你大约能够兑现任何你能假造到的布局。布局世襲自UICollectionViewLayout那些抽象基类。iOS6中以UICollectionViewFlowLayout类的款型提议了多少个具体的布局实现。

效果图1.png

- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:rect; // return an array layout attributes instances for all the views in the given rect

@property (nonatomic) CGFloat minimumLineSpacing;

至于UICollectionView,别的的同事早已介绍过啊,可以看这里

笔者们能够看见那么些流式构造,大家得以自定义 构造,继承与UICollectionViewFlowLayout

  • 以此办法的重临值是一个数组(数组里面存放着rect范围内有所因素的结构属性)
  • 本条情势的重临值决定了rect范围内部存款和储蓄器有因素的排布
  • 归来数组内寄存的是 UICollectionViewLayoutAttributes 对象, 一个 cell 对应一个 UICollectionViewLayoutAttributes 对象, 该对象说了算了 cell 的 frame

2、设置列与列之间的间隔最小间距

笔者们写一个精短的小demo,效果相近那样
UICollectionViewFlowLayout

本人前些天将 首要代码 贴出来 ,希望对正在利用UICollectionView的同学有所支持

@property (nonatomic) CGFloat minimumInteritemSpacing;

那是最简易的流水布局:UICollectionViewFlowLayout。类如其义,它提供多个水流布局,item(形似UITableView中的cell)会排列在上叁个item的入手,假使荧屏空间相当不够,它会自动排到下一行,和水流相像。

自定义 布局,继承与 UICollectionViewFlowLayout
CoustomFlowLayOut.m

- prepareLayout;

3、设置每一种item的轻重

代码如下:

  • (instancetype)init
    {
    if (self = [super init]) {
    }
    return self;
    }
  • 用来做构造的开头化操作
  • 不提议在 init 方法中张开构造的初始化操作
  • 早晚要调用[super prepareLayout], 官方文档中有妇孺皆知注释, Subclasses should always call super if they override.

@property (nonatomic) CGSize itemSize;

  • (UICollectionView *)collectionView
    {
    if (!_collectionView) {
    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
    self.currentLayout = layout;
    _collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 150, [UIScreen mainScreen].bounds.size.width, 240) collectionViewLayout:layout];
    _collectionView.delegate = self;
    _collectionView.dataSource = self;
    [_collectionView registerClass:[ZQCollectionViewCell class] forCellWithReuseIdentifier:@"cell"];
    }

    return _collectionView;
    }

/**

4、设置每一个Item的价值评估大小,日常无需设置

我们前几天想达成一个如此的法力:
当左右拖动item的时候,挨近显示屏中央item放大,远隔宗旨的item减少
左右滑动的时候,甘休下来的item的中坚永世和荧屏主题对齐

  • 当collectionView的来得范围产生变动的时候,是不是要求再度刷新结构
  • 若是重新刷新布局,就能够再一次调用下边包车型客车格局:
    1.prepareLayout
    2.layoutAttributesForElementsInRect:方法
    */
- shouldInvalidateLayoutForBoundsChange:newBounds; // return YES to cause the collection view to requery the layout for geometry information

@property (nonatomic) CGSize estimatedItemSize NS_AVAILABLE_IOS;

职能如图:
linear

若是回去YES,那么collectionView显示的限量产生更动时,就能再度刷新布局一旦重新刷新布局,就能够按顺序调用下边包车型地铁措施:

5、设置布局方向

首先,大家须求自定义UICollectionViewLayout。由于须求效果依然维持流水特性,大家接纳世袭UICollectionViewFlowLayout。须求重写的主意如下:

  • (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
    {
    return YES;
    }
  • prepareLayout
  • layoutAttributesForElementsInRect:

@property (nonatomic) UICollectionViewScrollDirection scrollDirection;

  • (voidState of QatarprepareLayout:该情势是历次构造时有个别考虑专门的学问,能够在那地做一些开始化的操作,记得调用super完结!
  • (BOOL卡塔尔shouldInvalidateLayoutForBoundsChange:(CGRectState of QatarnewBounds:当布局的境界发送更改的时候,会询问该措施是或不是再次构造
  • (NSArray *卡塔尔国layoutAttributesForElementsInRect:(CGRect卡塔尔(قطر‎rect:再次回到可以知道的rect中负有的Elements的布局属性(UICollectionViewLayoutAttributes)。在UICollectionViewLayoutAttributes可安装item的size、center、transform等等属性,来标准定制item的任务和形变.UICollectionViewFlowLayout对该方式有贰个暗许完结,可使item流水式排列。而UICollectionViewLayout则完全都以空达成,须要大家和好总结
  • (CGPoint卡塔尔(قطر‎targetContentOffsetForProposedContentOffset:(CGPoint卡塔尔proposedContentOffset withScrollingVelocity:(CGPointState of Qatarvelocity:当item被滑动自行甘休时,我们能够依赖这些措施设定item停在大家意在之处

美高梅网投网址,/**

6、设置头视图尺寸大小

代码如下:

  • 用来做构造的初步化操作(不提议在init方法中展开布局的伊始化操作)
    */
- targetContentOffsetForProposedContentOffset:proposedContentOffset withScrollingVelocity:velocity; // return a point at which to rest after scrolling - for layouts that want snap-to-point scrolling behavior

@property (nonatomic) CGSize headerReferenceSize;

  • (void)prepareLayout
    {
    [super prepareLayout];
    // 每个item的size
    self.itemSize = CGSizeMake(ITEM_SIZE, ITEM_SIZE);
    // 最小间距
    self.minimumLineSpacing = 50;
    // 横向滚动
    self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    // 内间距
    self.sectionInset = UIEdgeInsetsMake(90, (self.collectionView.bounds.size.width - ITEM_SIZE) * 0.5, 40, 150);
    }

  • (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
    {
    return YES;
    }

  • (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
    {
    // 当前显示器的rect
    CGRect visiableRect = {proposedContentOffset, self.collectionView.bounds.size};
    CGFloat currentCenterX = proposedContentOffset.x self.collectionView.bounds.size.width * 0.5;
    // 调用super完结能够拿走到当下rect中有所item的构造属性
    NSArray *attributesArray = [super layoutAttributesForElementsInRect:visiableRect];
    CGFloat adjustDistance = MAXFLOAT;
    // 计算间隔核心点近些日子的item,来算偏移量
    for (UICollectionViewLayoutAttributes *attributes in attributesArray) {
    if (CGRectIntersectsRect(attributes.frame, visiableRectState of Qatar卡塔尔 {// 在显示屏内
    CGFloat x = attributes.center.x;
    if (ABS(x - currentCenterX) < ABS(adjustDistance)) {
    adjustDistance = x - currentCenterX;
    }
    }
    }

    return CGPointMake(proposedContentOffset.x adjustDistance, proposedContentOffset.y);
    }

  • (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
    {
    CGRect visiableRect = {self.collectionView.contentOffset, self.collectionView.bounds.size};
    CGFloat currentCenterX = self.collectionView.contentOffset.x self.collectionView.bounds.size.width * 0.5;
    NSArray *attributesArray = [super layoutAttributesForElementsInRect:visiableRect];
    for (UICollectionViewLayoutAttributes *attributes in attributesArray) {
    if (CGRectIntersectsRect(attributes.frame, visiableRect卡塔尔卡塔尔国 {// 在显示屏内
    CGFloat itemCenterX = attributes.center.x;
    // 设定贰个推广的周到,公式我们能够友善来定,效果形似就能够
    CGFloat scale = 1 SCALE_FACTOR * (1 - (ABS(itemCenterX - currentCenterX) / SCALE_BIG_DISTANCE));
    attributes.transform3D = CATransform3DMakeScale(scale, scale, 1.0);
    }
    }
    return attributesArray;
    }

这么些法子的重返值,就调节了collectionView停止滚动时的偏移量参数:

7、设置尾视图尺寸大小

以上是世襲UICollectionViewFlowLayout的构造,假使我们想做三次越来越深等级次序的定制,大家能够直接世袭UICollectionViewLayout来完全自定义布局,要重写的主意和UICollectionViewFlowLayout相符,只是大家须要团结来促成那几个办法:

  • (void)prepareLayout
    {
    [super prepareLayout];

    // 水平滚动
    self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    // 设置内边距
    CGFloat inset = (self.collectionView.frame.size.width - self.itemSize.width) * 0.5;
    self.sectionInset = UIEdgeInsetsMake(0, inset, 0, inset);
    }

  • proposedContentOffset:collectionView截止滚动时最终的撼动
  • velocity:滚动速率,通过那些参数能够领悟滚动的趋向

@property (nonatomic) CGSize footerReferenceSize;

  • (NSArray *卡塔尔layoutAttributesForElementsInRect:(CGRectState of Qatarrect:须求团结新建UICollectionViewLayoutAttributes,也得以由此上边包车型客车方式2成就
  • (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *State of Qatarindex帕特h:该方式鲜明当前indexPath下的item的布局属性

/**
UICollectionViewLayoutAttributes attrs;
1.三个cell对应多少个UICollectionViewLayoutAttributes对象
2.UICollectionViewLayoutAttributes目的说了算了cell的frame
/
/**

8、设置分区的艾德geInset

代码如下:

  • 本条点子的重回值是叁个数组(数组里面存放着rect范围内有着因素的结构属性)
  • 这一个方法的重临值决定了rect范围内全数因素的排布(frame)
    */
  • 调用 [super layoutAttributesForElementsInRect], 获得父类算好的 cell 构造属性数组
  • 遍历布局属性数组, 修改每种 cell 构造属性的缩放比例 scale (原则应该是在自然范围内, cell 间隔 collectionView 的 contentView 大旨线越近, cell 展现比例越大卡塔尔
  • 在父类算好的底子上扩充校勘 (transform卡塔尔, 改善完后, 再次回到那一个数组就可以

@property (nonatomic) UIEdgeInsets sectionInset;

  • (void)prepareLayout
    {
    [super prepareLayout];
    }

  • (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
    {
    return YES;
    }

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

  • (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
    {
    NSInteger count = [self.collectionView numberOfItemsInSection:0];
    CGPoint currentCenter = CGPointMake(self.collectionView.contentOffset.x self.collectionView.bounds.size.width * 0.5, self.collectionView.bounds.size.height * 0.5);
    UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    attributes.size = CGSizeMake(ITEM_SIZE, ITEM_SIZE);

    CGFloat angelDelta = M_PI * 2 / count;
    CGFloat angel = M_PI_2 - angelDelta * indexPath.row;
    attributes.center = CGPointMake(currentCenter.x CIRCLE_RADIUS * cosf(angel), currentCenter.y CIRCLE_RADIUS * sinf(angel));
    return attributes;

9、上面这七个艺术设置分区的头视图和尾视图是不是始终平素在荧屏上方和上边

}
以上可达成贰个环形(circle)布局, demo中还增加了点击item就把该item删除的风云
circel

  • (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
    {
    // 得到super已经计算好的结构属性
    NSArray *array = [super layoutAttributesForElementsInRect:rect] ;

    // 总括collectionView最核心点的x值
    CGFloat centerX = self.collectionView.contentOffset.x self.collectionView.frame.size.width * 0.5;

    // 在原来构造属性的根基上,举行微调
    for (UICollectionViewLayoutAttributes *attrs in array) {
    // cell的中央点x 和 collectionView最中央点的x值 的间距
    CGFloat delta = ABS(attrs.center.x - centerX);

      // 根据间距值 计算 cell的缩放比例
      CGFloat scale = 1 - delta / self.collectionView.frame.size.width;
    
      // 设置缩放比例
      attrs.transform = CGAffineTransformMakeScale(scale, scale);
    

    }
    return array;
    }

- (NSArray *)layoutAttributesForElementsInRect:rect{ // 获得super已经计算好的布局属性 NSArray *array = [super layoutAttributesForElementsInRect:rect]; // 计算collectionView最中心点的x值 CGFloat centerX = self.collectionView.contentOffset.x   self.collectionView.frame.size.width * 0.5; // 在原有布局属性的基础上,进行微调 for (UICollectionViewLayoutAttributes *attrs in array) { // cell的中心点x 和 collectionView最中心点的x值 的间距 CGFloat delta = ABS(attrs.center.x - centerX); // 根据间距值 计算 cell的缩放比例 CGFloat scale = 1 - delta / self.collectionView.frame.size.width; // 设置缩放比例 attrs.transform = CGAffineTransformMakeScale(scale, scale); } return array;}

@property (nonatomic) BOOL sectionHeadersPinToVisibleBounds NS_AVAILABLE_IOS;

还是能够做二个看似蜂巢的结构:

/**

表示当collectionView展现的节制爆发变动时,就能够再也刷新布局, 一旦刷新构造, 就能按顺序调用:

@property (nonatomic) BOOL sectionFootersPinToVisibleBounds NS_AVAILABLE_IOS;

  • (CGSize)collectionViewContentSize
    {
    NSInteger count = [self.collectionView numberOfItemsInSection:0];
    return CGSizeMake(0, (count / COL)* count);
    }

  • (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
    {
    UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

    UICollectionView *collection = self.collectionView;

    float x = (SIZE self.margin) * (indexPath.item % COL 1) * 0.75 40;
    float y = (SIZE self.margin) * (indexPath.item / COL 0.5) * cos(M_PI * 30.0f / 180.0f) 20;
    if (indexPath.item % 2 == 1) {
    y = (SIZE self.margin) * 0.5 * cosf(M_PI * 30.0f / 180.0f);
    }

    attributes.center = CGPointMake(x collection.contentOffset.x, y collection.contentOffset.y);
    attributes.size = CGSizeMake(SIZE, SIZE * cos(M_PI * 30.0f / 180.0f));

    return attributes;
    }

  • 以此方式的重返值,就调控了collectionView甘休滚动时的偏移量
- prepareLayout;

- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:rect; // return an array layout attributes instances for all the views in the given rect

- targetContentOffsetForProposedContentOffset:proposedContentOffset withScrollingVelocity:velocity{ // 计算出最终显示的矩形框 CGRect rect; rect.origin.y = 0; rect.origin.x = proposedContentOffset.x; rect.size = self.collectionView.frame.size; // 获得super已经计算好的布局属性 NSArray *array = [super layoutAttributesForElementsInRect:rect]; // 计算collectionView最中心点的x值 CGFloat centerX = proposedContentOffset.x   self.collectionView.frame.size.width * 0.5; // 存放最小的间距值 CGFloat minDelta = MAXFLOAT; for (UICollectionViewLayoutAttributes *attrs in array) { if (ABS > ABS(attrs.center.x - centerX)) { minDelta = attrs.center.x - centerX; } } // 修改原有的偏移量 proposedContentOffset.x  = minDelta; return proposedContentOffset;} ```#### 04 -  关于 scale - 缩放比例 计算出 cell 的中心线和 collectionView 的 contentView 的中心线的绝对距离 delta- 计算collectionView最中心点的x值 ``` CGFloat centerX = self.collectionView.contentOffset.x   self.collectionView.frame.size.width * 0.5; ```- 计算cell的中心点 x 和 collectionView 最中心点的 x 值的间距

CGFloat delta = ABS(attrs.center.x - centerX);```

见状此间作者想大家也领悟了,UICollectionViewFlowLayout相对于父类加多的性子就是越来越好地开创的报表视图。常用的有两连串型的 collection view 构造:

-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray *arr = [super layoutAttributesForElementsInRect:rect];
if ([arr count] > 0) {
return arr;
}
NSMutableArray *attributes = [NSMutableArray array];
for (NSInteger i = 0 ; i < [self.collectionView numberOfItemsInSection:0 ]; i ) {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
[attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];
}
return attributes;
}

*/

  • 借助 delta, 加一定全面, 算出 scale

1.独门于剧情的构造总计。那正是你所明白的像 UITableView 和 UICollectionViewFlowLayout 这几个情状。种种 cell 的职责和外观不是基于其出示的内容,但具备 cell 的突显顺序是依靠内容的一一。能够把暗中同意的 flow layout 做为例子。每一个 cell 都依照前一个 cell 放置(或然只要未有丰富的空间,则从下一行开端卡塔尔国。构造对象无须访问实际数据来测算布局,当时最低价的正是用系统封装好的UICollectionViewFlowLayout类了,当然你能够一贯用,也得以继续它,自定义一些表格流。

其中cell的样式:

  • (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
    {
    // 总括出最终展现的矩形框
    CGRect rect;
    rect.origin.y = 0;
    rect.origin.x = proposedContentOffset.x;
    rect.size = self.collectionView.frame.size;

    // 得到super已经总结好的构造属性
    NSArray *array = [super layoutAttributesForElementsInRect:rect];

    // 计算collectionView最核心点的x值
    CGFloat centerX = proposedContentOffset.x self.collectionView.frame.size.width * 0.5;

    // 存放最小的间隔值
    CGFloat minDelta = MAXFLOAT;
    for (UICollectionViewLayoutAttributes *attrs in array) {
    if (ABS(minDelta) > ABS(attrs.center.x - centerX)) {
    minDelta = attrs.center.x - centerX;
    }
    }

    // 修正原有的偏移量
    proposedContentOffset.x = minDelta;
    return proposedContentOffset;
    }

2.基于剧情的布局总计。布局对象直接待上访谈 collection view 的数据源,依据数量源再钦命相应的构造。在大多气象下,构造对象不仅仅供给抽取当前可以看到cell 的多寡,还需求从全部记录中收取一些垄断当前怎样 cell 可以预知的数据。所以只要有三个依靠内容的构造,那正是暗中表示你需求写自定义的布局类了,同时不能够利用自定义的 UICollectionViewFlowLayout。

  • (instancetype)initWithFrame:(CGRect)frame

自定义cell的话,就是唯有一张图纸,这里不再赘述,调节器里
mainViewController.m

CGFloat scale = 1 - delta / self.collectionView.frame.size.width;

{

  • (void)viewDidLoad {
    [super viewDidLoad];

    // 创设构造
    CoustomFlowLayOut *layout = [[CoustomFlowLayOut alloc] init];
    layout.itemSize = CGSizeMake(100, 100);

    // 创建CollectionView
    CGFloat collectionW = self.view.frame.size.width;
    CGFloat collectionH = 200;
    CGRect frame = CGRectMake(0, 150, collectionW, collectionH);
    UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:frame collectionViewLayout:layout];
    collectionView.dataSource = self;
    collectionView.delegate = self;
    [self.view addSubview:collectionView];

    // 注册
    [collectionView registerNib:[UINib nibWithNibName:NSStringFromClass([CYPhotoCell class]) bundle:nil] forCellWithReuseIdentifier:CYPhotoId];
    }

  • 相对与功力简单的 TableView, 能完结复杂的定制效果
  • 其间缓存机制, cell 复用
  • TableView 雷同的 dataSource, delegate 方法, 轻便易用的 API

好了,原理介绍完了下边批注一下UICollectionViewFlowLayout用法和注意点(对于父类UICollectionViewFLayout的上课供给等到下篇文章哦):

if (self = [super initWithFrame:frame]) {

    self.backgroundColor = ZQRandomColor;

    CGFloat longSide = SIZE * 0.5 * cosf(M_PI * 30 / 180);

    CGFloat shortSide = SIZE * 0.5 * sinf(M_PI * 30 / 180);

    UIBezierPath *path = [UIBezierPath bezierPath];

    [path moveToPoint:CGPointMake(0, longSide)];

    [path addLineToPoint:CGPointMake(shortSide, 0)];

    [path addLineToPoint:CGPointMake(shortSide   SIZE * 0.5, 0)];

    [path addLineToPoint:CGPointMake(SIZE, longSide)];

    [path addLineToPoint:CGPointMake(shortSide   SIZE * 0.5, longSide * 2)];

    [path addLineToPoint:CGPointMake(shortSide, longSide * 2)];

    [path closePath];



    CAShapeLayer *maskLayer = [CAShapeLayer layer];

    maskLayer.path = [path CGPath];



    self.layer.mask = maskLayer;

}

return self;

pragma mark - <UICollectionViewDataSource>

  • (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
    {
    return 20;
    }

  • (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
    CYPhotoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CYPhotoId forIndexPath:indexPath];

    cell.imageName = [NSString stringWithFormat:@"%zd", indexPath.item 1];

    return cell;
    }

重写prepareLayout方法

}

pragma mark - <UICollectionViewDelegate>

  • (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
    {
    NSLog(@"------%zd", indexPath.item);
    }
    @end

上边正是 重要的代码,就足以相当的轻松的达成 上边图片的职能

我们还大概 见过商城中的 商品中的布局 ,相像是那样的,

美高梅网投网址 4

效果图.png

骨子里上边包车型客车这种效应也相当轻易完结,只要自己自定义架构就可以了,只是这么些构造比 下边这种构造更眼花缭乱一点,可是总体的笔触依旧类似的,正是 自定义 布局,自定义cell,然后决定器 来接收使用它们,在这里地 作者将重大的代码贴出来,让大家参照他事他说加以侦察,希望对大家深切理解认知UICollectionView有好的相助
长期以来的自己先贴出 自定义layOut的 代码
.h中

  • UICollectionView 提供的自定义 layout 功用能够方便定制超多职能, 比方电子商务利用遍布的瀑布流, tagView 等等
  • UITableView 是以行为单位, 成效有限, 而 UICollectionView 能够方便的通过自定 layout 完结各样分歧效用
  • UICollectionView 也能够通过自定 layout 实现 UITableView
  • UICollectionView 内部的巡回利用机制得以有效的节约内部存款和储蓄器, 幸免程序 crash

- 效用:在这里个格局中做一些开端化操作

功能如图:
honeycomb

import <UIKit/UIKit.h>

@class MKMasonryViewLayout;

@protocol MKMasonryViewLayoutDelegate <NSObject>
@required

  • (CGFloat) collectionView:(UICollectionView) collectionView
    layout:(MKMasonryViewLayout
    ) layout
    heightForItemAtIndexPath:(NSIndexPath*) indexPath;
    @end

@interface MKMasonryViewLayout : UICollectionViewLayout
@property (nonatomic, assign) NSUInteger numberOfColumns;
@property (nonatomic, assign) CGFloat interItemSpacing;
@property (weak, nonatomic) IBOutlet id<MKMasonryViewLayoutDelegate> delegate;
@end

.m中

达成的数不尽别的流行效果会在其后贴出

- 注意:一定要调用[super prepareLayout]

import "MKMasonryViewLayout.h"

@interface MKMasonryViewLayout (/Private Methods/)
@property (nonatomic, strong) NSMutableDictionary *lastYValueForColumn;
@property (strong, nonatomic) NSMutableDictionary *layoutInfo;
@end

@implementation MKMasonryViewLayout

-(void) prepareLayout {

//群集试图 构造 前 会调用这些点子,在这里地将 布局物件的边框都精兵简政好 缓存到某些地点

self.numberOfColumns = 3;
self.interItemSpacing = 12.5;

CGFloat currentColumn = 0;
CGFloat fullWidth = self.collectionView.frame.size.width;
CGFloat availableSpaceExcludingPadding = fullWidth - (self.interItemSpacing * (self.numberOfColumns 1));
CGFloat itemWidth = availableSpaceExcludingPadding / self.numberOfColumns;//各类物件的宽窄

self.lastYValueForColumn = [NSMutableDictionary dictionary];

self.layoutInfo = [NSMutableDictionary dictionary];
NSIndexPath *indexPath;
NSInteger numSections = [self.collectionView numberOfSections];

for(NSInteger section = 0; section < numSections; section ) {
//collectionView 是 横着 排列的,并非 竖着排列的
NSInteger numItems = [self.collectionView numberOfItemsInSection:section];
//每一种 section 上含蓄多少个 nuMItems
for(NSInteger item = 0; item < numItems; item ){
indexPath = [NSIndexPath indexPathForItem:item inSection:section];

  UICollectionViewLayoutAttributes *itemAttributes =
  [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

  CGFloat x = self.interItemSpacing   (self.interItemSpacing   itemWidth) * currentColumn;
  CGFloat y = [self.lastYValueForColumn[@(currentColumn)] doubleValue];

  CGFloat height = [((id<MKMasonryViewLayoutDelegate>)self.collectionView.delegate)
                    collectionView:self.collectionView
                    layout:self
                    heightForItemAtIndexPath:indexPath];

  itemAttributes.frame = CGRectMake(x, y, itemWidth, height);
  y = height;
  y  = self.interItemSpacing;

  self.lastYValueForColumn[@(currentColumn)] = @(y);

  currentColumn   ;
  if(currentColumn == self.numberOfColumns) currentColumn = 0;
  self.layoutInfo[indexPath] = itemAttributes;
}

}
}

  • (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {

    NSMutableArray *allAttributes = [NSMutableArray arrayWithCapacity:self.layoutInfo.count];

    [self.layoutInfo enumerateKeysAndObjectsUsingBlock:^(NSIndexPath *indexPath,
    UICollectionViewLayoutAttributes *attributes,
    BOOL *stop) {

    if (CGRectIntersectsRect(rect, attributes.frame)) {
    [allAttributes addObject:attributes];
    }
    }];
    return allAttributes;
    }

-(CGSize) collectionViewContentSize {

NSUInteger currentColumn = 0;
CGFloat maxHeight = 0;
do {
CGFloat height = [self.lastYValueForColumn[@(currentColumn)] doubleValue];
if(height > maxHeight)
maxHeight = height;
currentColumn ;
} while (currentColumn < self.numberOfColumns);

return CGSizeMake(self.collectionView.frame.size.width, maxHeight);
}

@end

上面正是 完整的把想要的结构 给 安顿好了,雷同自定义cell这里也不 多谢,现在把 调控器的代码贴出来!

接待关切小编, 点个向往,如有闲钱,迎接打赏。

重写layoutAttributesForElementsInRect:方法

import "SCTViewController.h"

@interface SCTViewController ()<UICollectionViewDataSource, UICollectionViewDelegate, MKMasonryViewLayoutDelegate, UICollectionViewDelegateFlowLayout>

@end

@implementation SCTViewController

  • (void)viewDidLoad
    {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    }

  • (void)didReceiveMemoryWarning
    {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }

  • (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {

    return 1;
    }

  • (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {

    return 40;
    }

  • (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier
    forIndexPath:indexPath];
    cell.backgroundColor = [UIColor redColor];
    return cell;
    }

// this will be called if our layout is UICollectionViewFlowLayout

  • (CGSize)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {

    CGFloat randomHeight = 100 (arc4random() % 140);
    return CGSizeMake(100, randomHeight); // 100 to 240 pixels tall
    }

// this will be called if our layout is MKMasonryViewLayout

  • (CGFloat) collectionView:(UICollectionView) collectionView
    layout:(MKMasonryViewLayout
    ) layout
    heightForItemAtIndexPath:(NSIndexPath*) indexPath {

    // we will use a random height from 100 - 400

    CGFloat randomHeight = 100 (arc4random() % 140);
    return randomHeight;
    }

@end

上面的代码就可以兑现上海教室中所要兑现的功效,希望得以帮到个位!希望个位提议宝贵意见!

- 作用:

- 那些形式的再次来到值是个数组

- 那个数组中存放的都以UICollectionViewLayoutAttributes对象

- UICollectionViewLayoutAttributes对象说了算了cell的排布形式

重写shouldInvalidateLayoutForBoundsChange:方法

- 作用:假设回到YES,那么collectionView展现的界定发生改变时,就能够再度刷新构造

- 一旦重新刷新结构,就能够按顺序调用上边包车型客车章程:

- prepareLayout

- layoutAttributesForElementsInRect:

重写targetContentOffsetForProposedContentOffset:withScrollingVelocity:方法

- 成效:再次回到值决定了collectionView结束滚动时最终的偏移量(contentOffset)

- 参数:

- proposedContentOffset:原来景况下,collectionView结束滚动时最终的偏移量

-velocity:滚动速率,通过那几个参数能够驾驭滚动的大方向


十分的少说了第一手上代码:

- (instancetype)init

{

if (self = [super init]) {

}

return self;

}

/**

* 当collectionView的显得范围发生退换的时候,是不是需求重新刷新结构

* 一旦重新刷新构造,就能再度调用上边包车型大巴秘籍:

1.prepareLayout

2.layoutAttributesForElementsInRect:方法

*/

- shouldInvalidateLayoutForBoundsChange:newBounds

{

return YES;

}

/**

* 用来做构造的伊始化操作(不提议在init方法中进行构造的开首化操作)

*/

- prepareLayout

{

[super prepareLayout];

// 水平滚动

self.scrollDirection = UICollectionViewScrollDirectionHorizontal;

// 设置内边距

CGFloat inset = (self.collectionView.frame.size.width - self.itemSize.width) * 0.5;

self.sectionInset = UIEdgeInsetsMake(0, inset, 0, inset);

}

/**

UICollectionViewLayoutAttributes *attrs;

1.二个cell对应一个UICollectionViewLayoutAttributes对象

2.UICollectionViewLayoutAttributes目的说了算了cell的frame

*/

/**

* 这么些办法的再次来到值是二个数组(数组里面寄放着rect范围内具有因素的构造属性)

* 那一个方式的重临值决定了rect范围内存有因素的排布

*/

- (NSArray *)layoutAttributesForElementsInRect:rect

{

// 取得super已经计算好的布局属性

NSArray *array = [super layoutAttributesForElementsInRect:rect];

// 计算collectionView最中央点的x值

CGFloat centerX = self.collectionView.contentOffset.x self.collectionView.frame.size.width * 0.5;

// 在原始布局属性的底子上,举办微调

for (UICollectionViewLayoutAttributes *attrs in array) {

// cell的主旨点x 和 collectionView最中央点的x值 的区间

CGFloat delta = ABS(attrs.center.x - centerX);

// 根据间隔值 计算 cell的缩放比例

CGFloat scale = 1 - delta / self.collectionView.frame.size.width;

// 设置缩放比例

attrs.transform = CGAffineTransformMakeScale(scale, scale);

}

return array;

}

/**

* 这几个办法的再次来到值,就决定了collectionView结束滚动时的偏移量

*/

- targetContentOffsetForProposedContentOffset:proposedContentOffset withScrollingVelocity:velocity

{

// 总括出最终展现的矩形框

CGRect rect;

rect.origin.y = 0;

rect.origin.x = proposedContentOffset.x;

rect.size = self.collectionView.frame.size;

// 获得super已经总括好的布局属性

NSArray *array = [super layoutAttributesForElementsInRect:rect];

// 计算collectionView最大旨点的x值

CGFloat centerX = proposedContentOffset.x self.collectionView.frame.size.width * 0.5;

// 存放最小的间距值

CGFloat minDelta = MAXFLOAT;

for (UICollectionViewLayoutAttributes *attrs in array) {

if (ABS > ABS(attrs.center.x - centerX)) {

minDelta = attrs.center.x - centerX;

}

}

// 修正原有的偏移量

proposedContentOffset.x = minDelta;

return proposedContentOffset;

}

TAG标签:
版权声明:本文由美高梅网投平台发布于美高梅网投网址,转载请注明出处:使用UICollectionView自定义样式01,的灵活使用