无限互联IOS开发之瀑布流的实现.docx

上传人:小飞机 文档编号:3572399 上传时间:2023-03-13 格式:DOCX 页数:14 大小:41.69KB
返回 下载 相关 举报
无限互联IOS开发之瀑布流的实现.docx_第1页
第1页 / 共14页
无限互联IOS开发之瀑布流的实现.docx_第2页
第2页 / 共14页
无限互联IOS开发之瀑布流的实现.docx_第3页
第3页 / 共14页
无限互联IOS开发之瀑布流的实现.docx_第4页
第4页 / 共14页
无限互联IOS开发之瀑布流的实现.docx_第5页
第5页 / 共14页
亲,该文档总共14页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《无限互联IOS开发之瀑布流的实现.docx》由会员分享,可在线阅读,更多相关《无限互联IOS开发之瀑布流的实现.docx(14页珍藏版)》请在三一办公上搜索。

1、无限互联IOS开发之瀑布流的实现IOS开发之瀑布流的实现(UICollectionView与UIScrollView) 瀑布流可以在保证图片原始比例的情况下,灵活的展现内容,相对于传统的使用相同大小的网格展现大量图片,要好上很多,而实现瀑布流的方式有很多种,网上比较流行的有三种实现方式。 1,使用UIScrollView,主要技术点在于视图的重用。 2,使用UITableView,这种方式应该是最易想到的,因为需要展现几列就用几个tabelview就ok了,而且不需要考虑重用,应为苹果已经做好了,只需要考虑如何在几列tabelView滑动的时候,保持同步不出现BUG。 3,使用UICollec

2、tionView,UICollectionView在iOS6中第一次被介绍,它与UITableView有许多相似点,但它多了一个布局类,而实现瀑布流,就与这个布局类有关。此种方式实现,也不需要考虑视图重用。 以上三种方式实现瀑布流,使用UICollectionView应该算是最简单的了,so,就重最简单的开始吧。 由于网络太差,所以展现的并不是网络上的图片,而是将用户相册中的图片读取出,并用瀑布流展现。 首先,遍历用户相册,将照片放到准备好的数组中。访问用户相册需要导入框架 objc view plaincopy 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 1

3、3. 14. 15. _images = NSMutableArray array; /创建相册库 library = ALAssetsLibrary alloc init; library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:(ALAssetsGroup *group, BOOLBOOL *stop) if (group) group enumerateAssetsUsingBlock:(ALAsset *result, NSUInteger index, BOOLBOOL *stop) if (resul

4、t) ALAssetRepresentation *resentation = result defaultRepresentation; CGImageRef imageRef = resentation.fullResolutionImage; UIImage *image = UIImage imageWithCGImage:imageRef; /将相片加入到数组中 self.images addObject:image; _collectionView reloadData; 16. 17. 18. 19. 20. 21. 22. 23. 24. ; failureBlock:(NSE

5、rror *error) ; 然后创建UICollectionView,注意这里放置UICollectionView的控制器要实现,UICollectionViewDelegateFlowLayout和UICollectionViewDatasource两个协议。 UICollectionView创建时需要传入一个布局对象,布局类继承自UICollectionViewLayout这个抽象基类,我们需要自定义布局对象,继承 UICollectionViewLayout的子类,UICollectionViewFlowLayout类,命名为WaterFlowLayout。 objc view pla

6、incopy 1. 2. interface WaterFlowLayout : UICollectionViewFlowLayout property (nonatomic,assign)id delegate; end objc view plaincopy 3. 4. 5. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. WaterFlowLayout *layout = WaterFlowLayout alloc init; _collectionView = UICollectionView alloc initWithFrame:UIScreen mainSc

7、reen.bounds collectionViewLayout:layout; _collectionView.dataSource = self; _collectionView.delegate = self; self.view addSubview:_collectionView; /注册单元格 _collectionView registerClass:WaterfallCell class forCellWithReuseIde ntifier:indf; 设置好代理,下面实现代理协议就行了,在这里同样子类化了UICollectionViewCell,命名为WaterfallCe

8、ll,并设置一个image属性,便于在协议方法中将照片传入。 objc view plaincopy 1. l interface WaterfallCell : UICollectionViewCelproperty (nonatomic,retain)UIImage *image; end 2. 3. 实现UICollectionViewDatasource协议。 objc view plaincopy 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. - (NSInteger)collectionView:(UICollectionView *

9、)collectionView numberOfItemsInSection:(NSInteger)section return _images.count; / The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath: - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSInd

10、exPath *)indexPath WaterfallCell *cell = collectionView dequeueReusableCellWithReuseIdentifier:indf forIndexPath:indexPath; UIImage *image = _imagesindexPath.item; cell.image = image; return cell; 实现UICollectionViewDelegateFlowLayout协议,将单元格的尺寸传入,这里让每张图片的宽度保持相同,高度等比例缩放。 objc view plaincopy 1. - (CGSi

11、ze)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 2. 3. UIImage *image = _imagesindexPath.item; 4. 5. 6. ; float height = self imgHeight:image.size.height Width:image.size.width return CGSizeMake(

12、100,height); /单元格中的间隙 - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UI7. 8. 9. 10. 11. 12. n CollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)sectio13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. UIEdgeInsets edgeInsets = 5,5,5,5; return edgeInsets

13、; - (float)imgHeight:(float)height Width:(float)width /单元格固定宽度为100 高度/宽度 = 压缩后高/100 float newHeigth = height/width*100; return newHeigth; 以上完成以后,控制器中的逻辑基本处理完毕,下面重写cell的setter方法,简单起见,我并没有创建Imageview显示图片,而是将图片直接绘制在了单元格上。 objc view plaincopy 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. - (void)se

14、tImage:(UIImage *)image if (_image != image) _image = image; self setNeedsDisplay; / Only override drawRect: if you perform custom drawing. / An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect / Drawing code float newHeigth = _image.size.height/_ima

15、ge.size.width*100; _image drawInRect:CGRectMake(0, 0, 100, newHeigth); 16. 17. 18. cell处理完毕后,下面就是最重要的布局类了,瀑布流就是依靠此类来展现的 首先在- (void)prepareLayout方法中得到cell的总个数,为每个cell确定自己的位置,此处用三列展现图片,当然列数可以随意设置,这取决与图片的宽度。 在layoutForItemAtIndexPath方法中为每个cell做布局,首先创建一个数组,存储三列的高度,每次遍历数组,找出最短列,将cell插入到最短列,而cell的高度和宽度,可以

16、通过调用前面视图控制器实现的代理协议得到。 objc view plaincopy 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. /准备布局 - (void)prepareLayout super prepareLayout; attributesDic = NSMutableDictionary dictionary; self.delegate = (id)self.collectionView.delegate; /获取cell的总个数 cellCoun

17、t = self.collectionView numberOfItemsInSection:0; if (cellCount = 0) return; colArr = NSMutableArray array;/列数 此处为3列 数组中存储每列的高度 float top = 0; for (int i = 0; i 3; i+) colArr addObject:NSNumber numberWithFloat:top; /循环调用layoutAttributesForItemAtIndexPath方法为每个cell计算布局,将 for (int i =0; i cellCount; i+

18、) self layoutForItemAtIndexPath:NSIndexPath indexPathForItem:i inSection indexPath传入,做为布局字典的key :0; 26. 27. objc view plaincopy 1. 下面是layoutForItemAtIndexPath方法的实现,这里用到了一个布局字典,其实就是将每个cell的位置信息与indexPath相对应,将它们存入字典中,之所以用到这个字典,是为了后面视图的检索。 objc view plaincopy 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.

19、14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. /此方法会多次调用 为每个cell布局 - (void)layoutForItemAtIndexPath:(NSIndexPath *)indexPath /调用协议方法得到cell间的间隙 UIEdgeInsets edgeInsets = self.delegate collectionView:self.collectionView layout:self insetForSectionAtIndex:indexPath.row; edge = edgeInsets; CGSize i

20、temSize = self.delegate collectionView:self.collectionView layout:self sizeForItemAtIndexPath:indexPath; NSInteger col = 0;/列数 /找出高度最小列,将cell加到最小列中 float shortHeigth = colArr objectAtIndex:col floatValue; for (int i = 1; i colArr.count; i+) float colHeight = colArr objectAtIndex:i floatValue; if (co

21、lHeight shortHeigth) shortHeigth = colHeight; col = i; float top = colArr objectAtIndex:col floatValue; /确定每个cell的frame CGRect frame = CGRectMake(edgeInsets.left + col*(edgeInsets.left+itemSiz /cell加入后,更新列高 e.width), top+edgeInsets.top, itemSize.width, itemSize.height); 27. 28. 29. 30. 31. 32. colAr

22、r replaceObjectAtIndex:col withObject:NSNumber numberWithFloat:to /每个cell的frame对应一个indexPath,存入字典中 attributesDic setObject:indexPath forKey:NSStringFromCGRect(frame); p + edgeInsets.top+itemSize.height; 为每个cell布局完毕后,还需要实现一个很重要的方法, - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect 此方法会传入一个U

23、ICollectionView当前可见的frame,需要返回需要显示的cell信息,数组中需要装入 UICollectionViewLayoutAttributes类创建的对象。 UICollectionViewLayoutAttributes类包含了collection view内item的所有相关布局属性。默认情况下,这个类包含frame,center,size,transform3D,alpha等信息,其实就是对每个cell位置信息的抽象。 当然你可以忽略传入的rect简单粗暴的将所有cell的布局信息放入数组中全部返回,我看了网上很多代码也都是这样做的,这样做是可以实现效果了,按coc

24、oa上的一篇关于UICollectionView译文的说法,此种做法是一种很幼稚的实现。因为当可见的cell远少于不可见cell的数量时,性能可能会灰常差,ok,为了使实现不那么幼稚,前面的布局字典就用到了。 遍历布局字典,将每个cell的frame与系统传入的frame使用CGRectIntersectsRect方法,判断字典中的那些cell的frame与传入的frame有交集如果结果为true说明此cell需要显示,那么就将cell对应的indexPath放入准备好的数组中,之所以需要indexPath,是因为UICollectionViewLayoutAttributes类需要index

25、Path来实例化,以此来对应每个cell。 objc view plaincopy 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. - (NSArray *)indexPathsOfItemsInRect:(CGRect)rect /遍历布局字典通过CGRectIntersectsRect方法确定每个cell的rect与传入的rect是否有交集,如果结果为true,则此cell应该显示,将布局字典中对应的indexPath加入数组 NSMutableArray *indexPaths = NSMutableArray array; for (NSStrin

26、g *rectStr in attributesDic) CGRect cellRect = CGRectFromString(rectStr); if (CGRectIntersectsRect(rect, cellRect) NSIndexPath *indexPath = attributesDicrectStr; indexPaths addObject:indexPath; 14. return indexPaths; objc view plaincopy 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. /此方法

27、会传入一个collectionView当前可见的rect,视图滑动时调用 /需要返回每个cell的布局信息,如果忽略传入的rect一次性将所有的cell布局信息返回,图片过多时性能会很差 - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect NSMutableArray *attributes = NSMutableArray array; /调用indexPathsOfItemsInRect方法,将rect传入,计算当前rect中应该出现的cell,返回值为cell的indexPath数组 NSArray *indexPath

28、s = self indexPathsOfItemsInRect:rect; for (NSIndexPath *indexPath in indexPaths) UICollectionViewLayoutAttributes *attribute = self layoutAttributes attributes addObject:attribute; return attributes; ForItemAtIndexPath:indexPath; 最后还需要实现 - (CGSize)collectionViewContentSize方法,此方法需要返回,collectionView内

29、容的大小,只需要遍历前面创建的存放列高的数组得到列高最大的一个作为高度返回就可以了 objc view plaincopy 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. /此方法返回collectionView内容的高度 - (CGSize)collectionViewContentSize CGSize size = self.collectionView.frame.size; /找出3列中最高的一列,作为collectionView的高度 float maxHeight = colArr objectAtIndex:0 floatValue; for (int i = 1; i maxHeight) maxHeight = colHeight; 13. 14. 15. 16. size.height = maxHeight; return size; 至此一个简单的瀑布流已经实现完毕,下面看一下效果图

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号