自定義流水布局(UICollectionViewFlowLayout的基本使用)


最終顯示的效果圖

思路:

1、UICollection的基本設置,並且創建一個繼承自UICollectionViewFlowLayout的類。(不能是UICollectionViewLayout,否則全部都需要自定義)

2、在UICollectionViewFlowLayout類中完成四步

  - 1)重寫prepareLayout方法進行基本的布局(cell在最左面的時候是在正中間),不能在init中布局,因為設置collectionView尺寸是在viewDidLoad中,而init在它之前調用,獲得的collectionView的尺寸是空的

  - 2)重寫shouldInvalidateLayoutForBoundsChange,當collectionView的顯示范圍發生改變的時候,讓其內部重新布局(即讓cell滾動起來)

  - 3)重寫layoutAttributesForElementsInRect方法,讓cell在左右滑動的時候,尺寸放大或縮小

  - 4)重寫targetContentOffsetForProposedContentOffset方法,讓最接近中心的cell在停在正中央。

 

代碼如下:

viewContorller中:

 1 #import "ViewController.h"
 2 #import "ZWLineLayout.h"
 3 @interface ViewController () <UICollectionViewDataSource>
 4 @end
 5 @implementation ViewController
 6 static  NSString *ZWCellID = @"cell";
 7 - (void)viewDidLoad {
 8     [super viewDidLoad];
 9     //若為UICollectionViewLayout,itemSize和scrollDirection都需要自己寫,下面的類繼承自UICollectionViewLayout
10     ZWLineLayout *layout = [[ZWLineLayout alloc] init];
11     layout.itemSize = CGSizeMake(160, 160);
12     CGRect rect = CGRectMake(0, 100, self.view.frame.size.width, self.view.frame.size.width * 0.6);
13     UICollectionView *collection = [[UICollectionView alloc] initWithFrame:rect collectionViewLayout:layout];
14     collection.dataSource = self;
15     collection.backgroundColor = [UIColor greenColor];
16     [self.view addSubview:collection];
17     [collection registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:ZWCellID];
18 }
19 
20 #pragma mark - 數據源方法
21 - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
22 {
23     return 10;
24 }
25 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
26 {
27     UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ZWCellID forIndexPath:indexPath];
28     cell.backgroundColor = [UIColor orangeColor];
29     return cell;
30 }

ZWLineLayout.m中

 1 #import "ZWLineLayout.h"
 2 
 3 @implementation ZWLineLayout
 4 
 5 /**
 6  * 用來做布局的初始化操作(不建議在init方法中進行布局的初始化操作)
 7  */
 8 - (void)prepareLayout
 9 {
10     [super prepareLayout];
11     //水平滾動
12     self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
13     
14     //
15     CGFloat margin = (self.collectionView.frame.size.width - self.itemSize.width) / 2;
16     self.collectionView.contentInset = UIEdgeInsetsMake(0, margin, 0, margin);
17 }
18 
19 /**
20  * 當collectionView的顯示范圍發生改變的時候,是否需要重新刷新布局
21  * 一旦重新刷新布局,就會重新調用下面的方法:
22  * 1.prepareLayout
23  * 2.layoutAttributesForElementsInRect:方法
24  */
25 - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
26 {
27     return YES;
28 }
29 
30 
31 /**
32  * 這個方法的返回值是一個數組(數組里面存放着rect范圍內所有元素的布局屬性)
33  * 這個方法的返回值決定了rect范圍內所有元素的排布(frame)
34  */
35 //需要在viewController中使用上ZWLineLayout這個類后才能重寫這個方法!!
36 - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
37 {
38     //讓父類布局好樣式
39     NSArray *arr = [super layoutAttributesForElementsInRect:rect];
40     //計算出collectionView的中心的位置
41     CGFloat ceterX = self.collectionView.contentOffset.x + self.collectionView.frame.size.width * 0.5;
42     /**
43      * 1.一個cell對應一個UICollectionViewLayoutAttributes對象
44      * 2.UICollectionViewLayoutAttributes對象決定了cell的frame
45      */
46     for (UICollectionViewLayoutAttributes *attributes in arr) {
47         //cell的中心點距離collectionView的中心點的距離,注意ABS()表示絕對值
48         CGFloat delta = ABS(attributes.center.x - ceterX);
49         //設置縮放比例
50         CGFloat scale = 1.1 - delta / self.collectionView.frame.size.width;
51         //設置cell滾動時候縮放的比例
52         attributes.transform = CGAffineTransformMakeScale(scale, scale);
53     }
54     
55     return arr;
56 }
57 
58 /**
59  * 這個方法的返回值,就決定了collectionView停止滾動時的偏移量
60  */
61 - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
62 {
63     // 計算出最終顯示的矩形框
64     CGRect rect;
65     rect.origin.y = 0;
66     rect.origin.x = proposedContentOffset.x;
67     rect.size = self.collectionView.frame.size;
68     
69     //獲得super已經計算好的布局的屬性
70     NSArray *arr = [super layoutAttributesForElementsInRect:rect];
71     
72     //計算collectionView最中心點的x值
73     CGFloat centerX = proposedContentOffset.x + self.collectionView.frame.size.width * 0.5;
74     
75     CGFloat minDelta = MAXFLOAT;
76     for (UICollectionViewLayoutAttributes *attrs in arr) {
77         if (ABS(minDelta) > ABS(attrs.center.x - centerX)) {
78             minDelta = attrs.center.x - centerX;
79         }
80     }
81     proposedContentOffset.x += minDelta;
82     return proposedContentOffset;
83 }
84 @end

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM