UICollectionViewLayout 学习(转)
2016-02-19 15:31
465 查看
收藏左中右对齐demo:https://github.com/lslwsjly/HYCollectionViewAlignedLayoutDemo
http://www.bubuko.com/infodetail-1037458.html
CircleLayout继承自UICollectionViewLayout,在这里先简单介绍一下UICollectionViewLayout
UICollectionViewLayout类是一个抽象基类,通过继承它以生成collection view的layout信息。layout对象的职责就是决定collection view中cells,supplementary views和decoration views的位置,当collection view请求这些信息时,layout对象会提供给collection view。collection view就使用laout对象提供的信息把相关的view显示在屏幕上。
注意:要使用UICollectionViewLayout必须先子类化它
子类化时需要注意的事项:
layout对象不负责创建views,它只提供layout(布局),view的创建是在collection view的data source中。layout对象定义了view的位置和size等布局属性。
collection view有三种可视元素需要layout:
Cells:cells是layout管理的主要元素。每一个cell代表了collection view中的单个数据item。一个collection view可以把cell放到一个section中,也可以把cell分为多个section。layout的主要职责就是组织collection view的cells。
Supplementary views:supplementary view也显示数据,但是与cells不同。并不像cell,supplementary view不可以被用户选择。相反,可以使用supplementary view来给一个section实现类似页眉和页脚,当然不仅仅是section,也可以是整个collection view。supplementary view是可选的,并且他们的使用和位置是由layout对象定义的。
Decoration views:decoration view是用于装饰的,不可以被用户选择,并且它的相关数据没有与collection view绑定。decoration view是另外一种supplementary view。类似supplementary view,decoration view也是可选的,,并且他们的使用和位置是由layout对象定义的。
collection view会在许多不同时间里面,请求这些元素的layout对象以获得相关 layout信息。每一个出现在屏幕中的cell和view的位置是有layout对象提供的。类似的,每次从collection view中插入或者删除item,相应的layout也会被添加或者移除。当然,collection view总是会限制layout对象数目:即只针对屏幕的可视范围。
需要重载的方法
每个layout对象都需要实现下面的方法:
这些方法具体作用,可以查阅相关的sdk即可知晓。
当collection view中的数据发生了改变,如插入或删除item,那么collection view会请求这些item的layout对象,以更新layout信息。特别是,任意的item被移动,添加或者删除了,必须要有它相关的layout信息来更新相关的新位置。对于移动一个items,collection view会使用标准的方法来检索item的layout属性。对于item的插入和删除,collection view会调用一些不同的方法,你应该重载这些方法,以提供相关的layout信息:
下面的代码中就是使用到了item的插入和删除。所以重载了下面两个方法:
对于layout在collection view中的作用非常重大,你的画面显示什么效果就看你如何定义layout了。更多相关信息还请阅读相关sdk中的内容。在此不再进行详细的讲解。
备注:
1自定义UICollectionViewFlowLayout时Xcode 报:
Logging only once for UICollectionViewFlowLayout cache mismatched frame
UICollectionViewFlowLayout has cached frame mismatch for index path {length = 2, path = 0 - 0} - cached value: {{-72.498976843927437, 14.090629367551388}, {447.84976661094447, 189.53807857184424}}; expected value: {{0, 35}, {401, 148}}
This is likely occurring because the flow layout subclass myFlowLayout is modifying attributes returned by UICollectionViewFlowLayout without copying them
解决方法:将所有重写的attributes加一个copy
http://www.bubuko.com/infodetail-1037458.html
CircleLayout继承自UICollectionViewLayout,在这里先简单介绍一下UICollectionViewLayout
UICollectionViewLayout类是一个抽象基类,通过继承它以生成collection view的layout信息。layout对象的职责就是决定collection view中cells,supplementary views和decoration views的位置,当collection view请求这些信息时,layout对象会提供给collection view。collection view就使用laout对象提供的信息把相关的view显示在屏幕上。
注意:要使用UICollectionViewLayout必须先子类化它
子类化时需要注意的事项:
layout对象不负责创建views,它只提供layout(布局),view的创建是在collection view的data source中。layout对象定义了view的位置和size等布局属性。
collection view有三种可视元素需要layout:
Cells:cells是layout管理的主要元素。每一个cell代表了collection view中的单个数据item。一个collection view可以把cell放到一个section中,也可以把cell分为多个section。layout的主要职责就是组织collection view的cells。
Supplementary views:supplementary view也显示数据,但是与cells不同。并不像cell,supplementary view不可以被用户选择。相反,可以使用supplementary view来给一个section实现类似页眉和页脚,当然不仅仅是section,也可以是整个collection view。supplementary view是可选的,并且他们的使用和位置是由layout对象定义的。
Decoration views:decoration view是用于装饰的,不可以被用户选择,并且它的相关数据没有与collection view绑定。decoration view是另外一种supplementary view。类似supplementary view,decoration view也是可选的,,并且他们的使用和位置是由layout对象定义的。
collection view会在许多不同时间里面,请求这些元素的layout对象以获得相关 layout信息。每一个出现在屏幕中的cell和view的位置是有layout对象提供的。类似的,每次从collection view中插入或者删除item,相应的layout也会被添加或者移除。当然,collection view总是会限制layout对象数目:即只针对屏幕的可视范围。
需要重载的方法
每个layout对象都需要实现下面的方法:
collectionViewContentSize shouldInvalidateLayoutForBoundsChange: layoutAttributesForElementsInRect: layoutAttributesForItemAtIndexPath: layoutAttributesForSupplementaryViewOfKind:atIndexPath: (如果layout 支持 supplementary views) layoutAttributesForDecorationViewWithReuseIdentifier:atIndexPath: (如果layout 支持 decoration views)
这些方法具体作用,可以查阅相关的sdk即可知晓。
当collection view中的数据发生了改变,如插入或删除item,那么collection view会请求这些item的layout对象,以更新layout信息。特别是,任意的item被移动,添加或者删除了,必须要有它相关的layout信息来更新相关的新位置。对于移动一个items,collection view会使用标准的方法来检索item的layout属性。对于item的插入和删除,collection view会调用一些不同的方法,你应该重载这些方法,以提供相关的layout信息:
initialLayoutAttributesForInsertedItemAtIndexPath: initialLayoutAttributesForInsertedSupplementaryElementOfKind:atIndexPath: finalLayoutAttributesForDeletedItemAtIndexPath: finalLayoutAttributesForDeletedSupplementaryElementOfKind:atIndexPath:
下面的代码中就是使用到了item的插入和删除。所以重载了下面两个方法:
initialLayoutAttributesForInsertedItemAtIndexPath: finalLayoutAttributesForDeletedItemAtIndexPath:
对于layout在collection view中的作用非常重大,你的画面显示什么效果就看你如何定义layout了。更多相关信息还请阅读相关sdk中的内容。在此不再进行详细的讲解。
// // CircleLayout.h // DevDiv_CollectionView_CircleLayout_Demo // // Created by BeyondVincent on 12-7-3. // Copyright (c) 2012年 DevDiv. All rights reserved. // #import @interface CircleLayout : UICollectionViewLayout @property (nonatomic, assign) CGPoint center; @property (nonatomic, assign) CGFloat radius; @property (nonatomic, assign) NSInteger cellCount; @end // // CircleLayout.m // DevDiv_CollectionView_CircleLayout_Demo // // Created by BeyondVincent on 12-7-3. // Copyright (c) 2012年 DevDiv. All rights reserved. // #import "CircleLayout.h" #define ITEM_SIZE 70 @implementation CircleLayout -(void)prepareLayout { [super prepareLayout]; CGSize size = self.collectionView.frame.size; _cellCount = [[self collectionView] numberOfItemsInSection:0]; _center = CGPointMake(size.width / 2.0, size.height / 2.0); _radius = MIN(size.width, size.height) / 2.5; } -(CGSize)collectionViewContentSize { return [self collectionView].frame.size; } - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)path { UICollectionViewLayoutAttributes* attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:path]; attributes.size = CGSizeMake(ITEM_SIZE, ITEM_SIZE); attributes.center = CGPointMake(_center.x + _radius * cosf(2 * path.item * M_PI / _cellCount), _center.y + _radius * sinf(2 * path.item * M_PI / _cellCount)); return attributes; } -(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect { NSMutableArray* attributes = [NSMutableArray array]; for (NSInteger i=0 ; i < self.cellCount; i++) { NSIndexPath* indexPath = [NSIndexPath indexPathForItem:i inSection:0]; [attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]]; } return attributes; } - (UICollectionViewLayoutAttributes *)initialLayoutAttributesForInsertedItemAtIndexPath:(NSIndexPath *)itemIndexPath { UICollectionViewLayoutAttributes* attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath]; attributes.alpha = 0.0; attributes.center = CGPointMake(_center.x, _center.y); return attributes; } - (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDeletedItemAtIndexPath:(NSIndexPath *)itemIndexPath { UICollectionViewLayoutAttributes* attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath]; attributes.alpha = 0.0; attributes.center = CGPointMake(_center.x, _center.y); attributes.transform3D = CATransform3DMakeScale(0.1, 0.1, 1.0); return attributes; } @end
备注:
1自定义UICollectionViewFlowLayout时Xcode 报:
Logging only once for UICollectionViewFlowLayout cache mismatched frame
UICollectionViewFlowLayout has cached frame mismatch for index path {length = 2, path = 0 - 0} - cached value: {{-72.498976843927437, 14.090629367551388}, {447.84976661094447, 189.53807857184424}}; expected value: {{0, 35}, {401, 148}}
This is likely occurring because the flow layout subclass myFlowLayout is modifying attributes returned by UICollectionViewFlowLayout without copying them
解决方法:将所有重写的attributes加一个copy
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{ NSArray * original = [super layoutAttributesForElementsInRect:rect]; NSArray * array = [[NSArray alloc] initWithArray:original copyItems:YES]; return array; }
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewLayoutAttributes* currentItemAttributes = [super layoutAttributesForItemAtIndexPath:indexPath]; UICollectionViewLayoutAttributes* currentItemAttributesCopy = [currentItemAttributes copy]; UIEdgeInsets sectionInset = [self evaluatedSectionInsetForItemAtIndex:indexPath.section]; BOOL isFirstItemInSection = indexPath.item == 0; CGFloat layoutWidth = CGRectGetWidth(self.collectionView.frame) - sectionInset.left - sectionInset.right; if (isFirstItemInSection) { [currentItemAttributesCopy leftAlignFrameWithSectionInset:sectionInset]; return currentItemAttributesCopy; } NSIndexPath* previousIndexPath = [NSIndexPath indexPathForItem:indexPath.item-1 inSection:indexPath.section]; CGRect previousFrame = [self layoutAttributesForItemAtIndexPath:previousIndexPath].frame; CGFloat previousFrameRightPoint = previousFrame.origin.x + previousFrame.size.width; CGRect currentFrame = currentItemAttributesCopy.frame; CGRect strecthedCurrentFrame = CGRectMake(sectionInset.left, currentFrame.origin.y, layoutWidth, currentFrame.size.height); // if the current frame, once left aligned to the left and stretched to the full collection view // widht intersects the previous frame then they are on the same line BOOL isFirstItemInRow = !CGRectIntersectsRect(previousFrame, strecthedCurrentFrame); if (isFirstItemInRow) { // make sure the first item on a line is left aligned [currentItemAttributesCopy leftAlignFrameWithSectionInset:sectionInset]; return currentItemAttributesCopy; } CGRect frame = currentItemAttributesCopy.frame; frame.origin.x = previousFrameRightPoint + [self evaluatedMinimumInteritemSpacingForItemAtIndex:indexPath.row]; currentItemAttributesCopy.frame = frame; return currentItemAttributesCopy; }
相关文章推荐
- Fuel3D人脸扫描
- 12.关于UIWindow的总结
- UIUC大学之Coursera课程Text Retrieval and Search Engines:Week 4 Quiz
- UIUC大学之Coursera课程Text Retrieval and Search Engines:Week 3 Quiz
- UIUC大学之Coursera课程Text Retrieval and Search Engines:Week 4 Practice Quiz
- UIUC大学之Coursera课程Text Retrieval and Search Engines:Week 3 Practice Quiz
- UIUC大学之Coursera课程Text Retrieval and Search Engines:Week 2 Quiz
- UIUC大学之Coursera课程Text Retrieval and Search Engines:Week 2 Practice Quiz
- <转载>拒绝卡顿——在WPF中使用多线程更新UI
- UIInterpolatingMotionEffect
- requirejs+cdn
- Java 入门 之 WindowBuilder 与 Swing 的安装
- UIButton的setTitle,system,custom
- EasyGui使用
- UIView的clipsTobounds属性
- Qt Quick学习笔记
- 模糊视图(毛玻璃效果) - UIVisualEffectView
- Android子线程更新UI两种方法
- 自定义弹窗(uialertview)
- ueditor自定义表单post过来的name