最終顯示的效果圖
思路:
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