经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » Android » 查看文章
UICollectionView 实现图片浏览效果
来源:jb51  时间:2022/7/20 13:09:11  对本文有异议

一、效果展示

废话开篇:利用 UICollectionView 简单实现一个图片浏览效果。

二、实现思路

1.封装 UICollectionViewLayout ,实现内部 UICollectionViewCell 的布局。

UICollectionViewLayout 在封装瀑布流的时候会用到,而且担负着核心功能的实现。其实从另一个角度也可以把 UICollectionViewLayout 理解成“数据源”,这个数据不是 UI 的展示项,而是 UI 的尺寸项。在内部进行预计算 UICollectionViewCell 的 frame。

UICollectionView 是 UIScrollView的子类,只不过,它里面子控件通过“重用”机制实现了优化,一些复用的复杂逻辑还是扔给了系统处理。开发过程中只负责对 UICollectionViewLayout 什么时候需要干什么进行自定义即可。

2.获取 UICollectionView 目前可见的 cells,通过进行缩放、旋转变换实现一些简单的效果。

3、自定义 cell ,修改锚点属性。

三、代码整理

1、PhotoBrowseViewLayout

这里有一点需要注意的,在 UICollectionViewLayout 内部会进行计算每一个 cell 的 frame,在计算过程中,为了更好的展示旋转变换,cell 的锚点会修改到 (0.5,1),那么,为了保证 UI 展示不变,那么,就需要将 y 增加 cell 高度的一半。

  1. #import "PhotoBrowseViewLayout.h"
  2. @interface PhotoBrowseViewLayout()
  3. @property(nonatomic,strong) NSMutableArray * attributeArray;
  4. @property(nonatomic,assign) CGFloat cellWidth;
  5. @property(nonatomic,assign) CGFloat cellHeight;
  6. @property(nonatomic,assign) CGFloat sep;
  7. @property(nonatomic,assign) int showCellNum;
  8. @end
  9. @implementation PhotoBrowseViewLayout
  10. - (instancetype)init
  11. {
  12. if (self = [super init]) {
  13. self.sep = 20;
  14. self.showCellNum = 2;
  15. }
  16. return self;
  17. }
  18. //计算cell的frame
  19. - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
  20. {
  21. if (self.cellWidth == 0) {
  22. self.cellWidth = **self**.collectionView.frame.size.width * 2 / 3.0;
  23. }
  24. if (self.cellHeight == 0) {
  25. self.cellHeight = self.collectionView.frame.size.height;
  26. }
  27. CGFloat x = (self.cellWidth + self.sep) * indexPath.item;
  28. //这里y值需要进行如此设置,以抵抗cell修改锚点导致的UI错乱
  29. CGFloat y = self.collectionView.frame.size.height / 2.0;
  30. UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
  31. attrs.frame = CGRectMake(x, y, self.cellWidth, self.cellHeight);
  32. return attrs;
  33. }
  34. //准备布局
  35. - (void)prepareLayout
  36. {
  37. [super prepareLayout];
  38. NSInteger count = [self.collectionView numberOfItemsInSection:0];
  39. for (int i = 0; i <count; i++) {
  40. UICollectionViewLayoutAttributes *attris = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
  41. [self.attributeArray addObject:attris];
  42. }
  43. }
  44. //返回全部cell的布局集合
  45. - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
  46. {
  47. return self.attributeArray;
  48. }
  49. //一次性提供UICollectionView 的 contentSize
  50. - (CGSize)collectionViewContentSize
  51. {
  52. NSInteger count = [self.collectionView numberOfItemsInSection:0];
  53. CGFloat maxWidth = count * self.cellWidth + (count - 1) * self.sep;
  54. return CGSizeMake(maxWidth, 0);
  55. }
  56. - (NSMutableArray *)attributeArray
  57. {
  58. if (!_attributeArray) {
  59. _attributeArray = [[NSMutableArray alloc] init];
  60. }
  61. return _attributeArray;
  62. }
  63. @end

2、PhotoBrowseCollectionViewCell

这里主要是进行了锚点修改(0.5,1),代码很简单。

  1. #import "PhotoBrowseCollectionViewCell.h"
  2. @interface PhotoBrowseCollectionViewCell()
  3. @property(nonatomic,strong) UIImageView * imageView;
  4. @end
  5. @implementation PhotoBrowseCollectionViewCell
  6. - (instancetype)initWithFrame:(CGRect)frame
  7. {
  8. if (self = [super initWithFrame:frame]) {
  9. //设置(0.5,1)锚点,以底部中点为轴旋转
  10. self.layer.anchorPoint = CGPointMake(0.5, 1);
  11. self.layer.masksToBounds = YES;
  12. self.layer.cornerRadius = 8;
  13. }
  14. return self;
  15. }
  16. - (void)setImage:(UIImage *)image
  17. {
  18. self.imageView.image = image;
  19. }
  20. - (UIImageView *)imageView
  21. {
  22. if (!_imageView) {
  23. _imageView = [[UIImageView alloc] init];
  24. _imageView.contentMode = UIViewContentModeScaleAspectFill;
  25. _imageView.backgroundColor = [UIColor groupTableViewBackgroundColor];
  26. [self.contentView addSubview:_imageView];
  27. }
  28. return _imageView;
  29. }
  30. - (void)layoutSubviews
  31. {
  32. [super layoutSubviews];
  33. self.imageView.frame = **self**.contentView.bounds;
  34. }
  35. @end

3、CollectPhotoBrowseView

CollectPhotoBrowseView 负责进行一些 cell 的图形变换。

  1. #import "CollectPhotoBrowseView.h"
  2. #import "PhotoBrowseCollectionViewCell.h"
  3. #import "PhotoBrowseViewLayout.h"
  4. @interface CollectPhotoBrowseView()<UICollectionViewDelegate,UICollectionViewDataSource>
  5. @property(nonatomic,strong) UICollectionView * photoCollectView;
  6. @end
  7. @implementation CollectPhotoBrowseView
  8. - (instancetype)initWithFrame:(CGRect)frame
  9. {
  10. if (self = [super initWithFrame:frame]) {
  11. [self makeUI];
  12. }
  13. return self;
  14. }
  15. - (void)makeUI{
  16. //设置自定义 UICollectionViewLayout
  17. PhotoBrowseViewLayout * photoBrowseViewLayout = [[PhotoBrowseViewLayout alloc] init];
  18. self.photoCollectView = [[UICollectionView alloc] initWithFrame:self.bounds collectionViewLayout:photoBrowseViewLayout];
  19. self.photoCollectView.delegate = self;
  20. self.photoCollectView.dataSource = self;
  21. [self.photoCollectView registerClass:[PhotoBrowseCollectionViewCell class] forCellWithReuseIdentifier:@"CELL"];
  22. self.photoCollectView.showsHorizontalScrollIndicator = NO;
  23. [self addSubview:self.photoCollectView];
  24. //执行一次可见cell的图形变换
  25. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  26. [self visibleCellTransform];
  27. });
  28. }
  29. - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
  30. {
  31. return 20;
  32. }
  33. - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
  34. {
  35. PhotoBrowseCollectionViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CELL" forIndexPath:indexPath];
  36. [cell setImage: [UIImage imageNamed:[NSString stringWithFormat:@"fd%ld",indexPath.item % 3 + 1]]];
  37. return cell;
  38. }
  39. #pragma mark - 滚动进行图形变换
  40. - (void)scrollViewDidScroll:(UIScrollView *)scrollView
  41. {
  42. //滑动的时候,动态进行cell图形变换
  43. [self visibleCellTransform];
  44. }
  45. #pragma mark - 图形变化
  46. - (void)visibleCellTransform
  47. {
  48. //获取当前可见cell的indexPath集合
  49. NSArray * visibleItems = [self.photoCollectView indexPathsForVisibleItems];
  50. //遍历动态进行图形变换
  51. for (NSIndexPath * visibleIndexPath in visibleItems) {
  52. UICollectionViewCell * visibleCell = [self.photoCollectView cellForItemAtIndexPath:visibleIndexPath];
  53. [self transformRotateWithView:visibleCell];
  54. }
  55. }
  56. //进行图形转换
  57. - (void)transformRotateWithView:(UICollectionViewCell *)cell
  58. {
  59. //获取cell在当前视图的位置
  60. CGRect rect = [cell convertRect:cell.bounds toView:self];
  61. //计算当前cell中轴线与中轴线的距离的比值
  62. float present = ((CGRectGetMidX(rect) - self.center.x) / (self.frame.size.width / 2.0));
  63. //根据位置设置选择角度
  64. CGFloat radian = (M_PI_2 / 15) * present;
  65. //图形角度变换
  66. CGAffineTransform transformRotate = CGAffineTransformIdentity;
  67. transformRotate = CGAffineTransformRotate(transformRotate, radian);
  68. //图形缩放变换
  69. CGAffineTransform transformScale = CGAffineTransformIdentity
  70. transformScale = CGAffineTransformScale(transformScale,1 - 0.2 * fabs(present),1 - 0.2 * fabsf(present));
  71. //合并变换
  72. cell.transform = CGAffineTransformConcat(transformRotate,transformScale);
  73. }
  74. @end

四、总结与思考

UICollectionView 也是 View,只不过系统为了更好的服务于开发者,快速高效的实现某些开发场景,进行了封装与优化,将复杂的逻辑单独的封装成一个管理类,这里就是 UICollectionViewLayout,交给它去做一些固定且复杂的逻辑。所以,自定义复杂UI的时候,就需要将功能模块足够细化,以实现更好的代码衔接。

以上就是UICollectionView 实现图片浏览效果的详细内容,更多关于UICollectionView 图片浏览的资料请关注w3xue其它相关文章!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号