iOS开发--横向流水布局实现

iOS开发--横向流水布局实现

前言:因为时间缘故,很少进行通俗易懂的算法思路讲解,这里先展示动态图片效果,然后后面的内容我就直接上关键源码了。

 

效果展示图;

源码百度云盘下载链接: http://pan.baidu.com/s/1eQOOixc 密码: duu8

 

源码:

1 //  PhotoCell.h

2 //  自定义流水布局

3 //

6 //

7

8 #import <UIKit/UIKit.h>

9

10 @interface PhotoCell : UICollectionViewCell

11

12 @property (nonatomic, strong) UIImage *image;

13

14 @end

15

16 ================两个文件的分水岭==================

17 //

18 //  PhotoCell.m

19 //  自定义流水布局

20 //

21 //  Created by xmg on 16/1/15.

22 //  Copyright © 2016 HeYang. All rights reserved.

23 //

24

25

26

27 #import "PhotoCell.h"

28

29 @interface PhotoCell ()

30 @property (weak, nonatomic) IBOutlet UIImageView *imageView;

31 @end

32

33 @implementation PhotoCell

34

35 - (void)awakeFromNib {

    36     // Initialization code

    37 }

38

39 - (void)setImage:(UIImage *)image

40 {

    41     _image = image;

    42

    43     _imageView.image = image;

    44

    45 }

46

47 @end

复制代码
  1 //
  2 //  PhotoLayout.h
  3 //  自定义流水布局
  4 //
  5 //  Created by xmg on 16/1/15.
  6 //  Copyright © 2016年 HeYang. All rights reserved.
  7 //
  8 
  9 #import <UIKit/UIKit.h>
 10 
 11 @interface PhotoLayout : UICollectionViewFlowLayout
 12 
 13 @end
 14 
 15 
 16 ==============两个文件的分水岭================
 17 
 18 //
 19 //  PhotoLayout.m
 20 //  自定义流水布局
 21 //
 22 //  Created by xmg on 16/1/15.
 23 //  Copyright © 2016年 HeYang. All rights reserved.
 24 //
 25 
 26 #import "PhotoLayout.h"
 27 #define XMGScreenW [UIScreen mainScreen].bounds.size.width
 28 @implementation PhotoLayout
 29 
 30 // 复杂效果: 分析 ->
 31 // cell离中心点距离越近(delta越小),就越大,越远,就越小
 32 // 距离中心点
 33 // 知道哪些cell需要缩放:显示出来的cell才需要进行布局
 34 
 35 
 36 
 37 // 给定一个区域,就返回这个区域内所有cell布局
 38 - (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
 39 {
 40     // 1.获取显示区域,bounds 而不是整个滚动区域,这样设置的子控件就控制在显示区域范围内了。
 41     CGRect visiableRect = self.collectionView.bounds;
 42 
 43     // 2.获取显示区域内的cell的布局
 44     NSArray *attributes = [super layoutAttributesForElementsInRect:visiableRect];
 45     
 46     
 47     
 48     // 3.遍历cell布局
 49     CGFloat offsetX = self.collectionView.contentOffset.x;
 50     for (UICollectionViewLayoutAttributes *attr in attributes) {
 51         // 3.1 计算下距离中心点距离
 52         CGFloat delta = fabs(attr.center.x - offsetX - XMGScreenW * 0.5);
 53         // 1 ~ 0.75
 54         CGFloat scale = 1 - delta / (XMGScreenW * 0.5) * 0.25;//1-(0~0.5) = 1~0.5 --> 1-(0~0.5)×0.25 = (1~0.75)
 55         attr.transform = CGAffineTransformMakeScale(scale, scale);
 56     }
 57     
 58     return attributes;
 59 }
 60 
 61 // Invalidate:刷新
 62 // 是否允许在拖动的时候刷新布局
 63 // 谨慎使用,YES:只要一滚动就会布局
 64 - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
 65 {
 66     return YES;
 67 }
 68 
 69 // 确定最终显示位置
 70 // 什么时候调用:手动拖动UICollectionView,当手指离开的时候,就会调用
 71 // 作用:返回UICollectionView最终的偏移量
 72 // proposedContentOffset:最终的偏移量
 73 - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
 74 {
 75     // 定位:判断下哪个cell里中心点越近,就定位到中间
 76     // 1.获取最终显示的区域
 77     CGRect targetRect = CGRectMake(proposedContentOffset.x, 0, self.collectionView.bounds.size.width, MAXFLOAT);
 78     
 79     // 2.获取最终显示cell的布局
 80     NSArray *attributes = [super layoutAttributesForElementsInRect:targetRect];
 81     
 82     // 3.遍历所有cell的布局,判断下哪个离中心点最近
 83     CGFloat minDelta = MAXFLOAT;
 84     
 85     for (UICollectionViewLayoutAttributes *attr in attributes) {
 86         // 3.1 计算下距离中心点距离
 87          CGFloat delta = attr.center.x - proposedContentOffset.x - XMGScreenW * 0.5;
 88         // 3.2 计算最小间距
 89         if (fabs(delta) < fabs(minDelta)) {
 90             minDelta = delta;
 91         }
 92     }
 93     
 94     proposedContentOffset.x += minDelta;
 95     
 96     if (proposedContentOffset.x < 0) {
 97         proposedContentOffset.x = 0;
 98     }
 99 
100     return proposedContentOffset;
101 }
102 
103 @end
复制代码

最后的关键代码:

复制代码
  1 //
  2 //  ViewController.m
  3 //  自定义流水布局
  4 //
  5 //  Created by xmg on 16/1/15.
  6 //  Copyright © 2016年 HeYang. All rights reserved.
  7 //
  8 
  9 #import "ViewController.h"
 10 #import "PhotoCell.h"
 11 #import "PhotoLayout.h"
 12 
 13 /*
 14  // a , b , c a = b + c
 15  //    int d = (2,3,5);
 16  
 17  // 高聚合,低耦合
 18  int a = ({
 19  int b = 2;
 20  int c = 3;
 21  a = b + c;
 22  20;
 23  });
 24  */
 25 
 26 /*
 27  UICollectionView注意点:
 28  1.初始化必须要传入布局,(流水布局:九宫格布局)
 29  2.UICollectionViewCell必须要注册
 30  3.必须自定义cell
 31  */
 32 
 33 
 34 #define XMGScreenW [UIScreen mainScreen].bounds.size.width
 35 static NSString * const ID = @"cell";
 36 @interface ViewController ()<UICollectionViewDataSource>
 37 
 38 @end
 39 
 40 @implementation ViewController
 41 
 42 // 思路:照片浏览布局:流水布局,在拖到的时候,在原来基础上重新计算下布局 -> 在原来功能上再添加功能,自定义流水布局
 43 - (void)viewDidLoad {
 44     [super viewDidLoad];
 45     // Do any additional setup after loading the view, typically from a nib.
 46     
 47     // 创建流水布局
 48     PhotoLayout *layout = ({
 49         layout = [[PhotoLayout alloc] init];
 50         // 尺寸
 51         layout.itemSize = CGSizeMake(180, 180);
 52         // 设置滚动方向:水平
 53         layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
 54         // 设置额外滚动区域
 55         CGFloat inset = (XMGScreenW - 180) * 0.5;
 56         layout.sectionInset = UIEdgeInsetsMake(0, inset, 0, inset);
 57         
 58         layout;
 59     });
 60     
 61     // 创建UICollectionView:默认为黑色
 62     UICollectionView *collectionView = ({
 63         collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
 64         collectionView.bounds = CGRectMake(0, 0, self.view.bounds.size.width, 200);
 65         collectionView.center = self.view.center;
 66         collectionView.backgroundColor = [UIColor cyanColor];
 67         collectionView.showsHorizontalScrollIndicator = NO;
 68         [self.view addSubview:collectionView];
 69         
 70         // 设置数据源
 71         collectionView.dataSource = self;
 72         collectionView;
 73     });
 74     
 75     // 注册cell
 76     [collectionView registerNib:[UINib nibWithNibName:NSStringFromClass([PhotoCell class]) bundle:nil] forCellWithReuseIdentifier:ID];
 77 }
 78 
 79 
 80 #pragma mark -UICollectionViewDataSource
 81 // 返回有多少个cell
 82 - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
 83 {
 84     return 20;
 85 }
 86 
 87 // 返回每个cell长什么样
 88 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
 89 {
 90     
 91     PhotoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ID forIndexPath:indexPath];
 92     
 93     NSString *imageName = [NSString stringWithFormat:@"%ld",indexPath.row + 1];
 94     
 95     cell.image = [UIImage imageNamed:imageName];
 96     
 97     return cell;
 98 }
 99 
100 @end
复制代码
posted @ 2017-06-12 10:23  李洪强  阅读(199)  评论(0编辑  收藏  举报