效果截圖:
7BAF9FD3-7A55-4ADF-8AC7-3675A9F41DAE.png
28B75949-ADC5-44D0-AD78-166377D416D5.png
關(guān)鍵的CustomFlowLayout類
//
// CustomFlowLayout.h
// 流水布局
//
// Created by zengchunjun on 17/1/4.
// Copyright ? 2017年 zengchunjun. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface CustomFlowLayout : UICollectionViewFlowLayout
@end
//
// CustomFlowLayout.m
// 流水布局
//
// Created by zengchunjun on 17/1/4.
// Copyright ? 2017年 zengchunjun. All rights reserved.
//
#import "CustomFlowLayout.h"
/*
自定義布局:只要了解5個方法
- (void)prepareLayout;
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity; // return a point at which to rest after scrolling - for layouts that want snap-to-point scrolling behavior
- (CGSize)collectionViewContentSize;
*/
@implementation CustomFlowLayout
/*
UICollectionViewLayoutAttributes:確定cell的尺寸
一個UICollectionViewLayoutAttributes對象就對應一個cell
拿到UICollectionViewLayoutAttributes相當于拿到cell
*/
// 重寫它方法,擴展功能
// 什么時候調(diào)用:collectionView第一次布局,collectionView刷新的時候也會調(diào)用
// 作用:計算cell的布局,條件:cell的位置是固定不變
// - (void)prepareLayout
//{
// [super prepareLayout];
//
// NSLog(@"%s",__func__);
//
//}
// 作用:指定一段區(qū)域給你這段區(qū)域內(nèi)cell的尺寸
// 可以一次性返回所有cell尺寸,也可以每隔一個距離返回cell
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
// NSLog(@"%s",__func__);
// 設置cell尺寸 => UICollectionViewLayoutAttributes
// 越靠近中心點,距離越小,縮放越大
// 求cell與中心點距離
// 1.獲取當前顯示cell的布局
NSArray *attrs = [super layoutAttributesForElementsInRect:self.collectionView.bounds];
for (UICollectionViewLayoutAttributes *attr in attrs) {
// 2.計算中心點距離
CGFloat delta = fabs((attr.center.x - self.collectionView.contentOffset.x) - self.collectionView.bounds.size.width * 0.5);
// 3.計算比例
CGFloat scale = 1 - delta / (self.collectionView.bounds.size.width * 0.5) * 0.25;
attr.transform = CGAffineTransformMakeScale(scale, scale);
}
return attrs;
}
// 什么時候調(diào)用:用戶手指一松開就會調(diào)用
// 作用:確定最終偏移量
// 定位:距離中心點越近,這個cell最終展示到中心點
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity{
// 拖動比較快 最終偏移量 不等于 手指離開時偏移量
CGFloat collectionW = self.collectionView.bounds.size.width;
// 最終偏移量
CGPoint targetP = [super targetContentOffsetForProposedContentOffset:proposedContentOffset withScrollingVelocity:velocity];
// 0.獲取最終顯示的區(qū)域
CGRect targetRect = CGRectMake(targetP.x, 0, collectionW, MAXFLOAT);
// 1.獲取最終顯示的cell
NSArray *attrs = [super layoutAttributesForElementsInRect:targetRect];
// 獲取最小間距
CGFloat minDelta = MAXFLOAT;
for (UICollectionViewLayoutAttributes *attr in attrs) {
// 獲取距離中心點距離:注意:應該用最終的x
CGFloat delta = (attr.center.x - targetP.x) - self.collectionView.bounds.size.width * 0.5;
if (fabs(delta) < fabs(minDelta)) {
minDelta = delta;
}
}
// 移動間距
targetP.x += minDelta;
if (targetP.x < 0) {
targetP.x = 0;
}
return targetP;
}
// Invalidate:刷新
// 在滾動的時候是否允許刷新布局
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{
return YES;
}
// 計算collectionView滾動范圍
//- (CGSize)collectionViewContentSize{
// return [super collectionViewContentSize];
//}
@end