"之前做瀑布流的时候接触过CollectionViewFlowLayout,但是一直没弄明白,所以昨天乘着有空钻一下这个知识点。"
这篇文章就不讲解CollectionView怎么创建啊什么的问题,这些问题可以直接看我最下面放的完整代码,注释很详细,这篇文章就直接讲我在这个Demo里怎么用CollectionViewFlowLayout的。
首先创建一个CollectionViewFlowLayout子类:
#import <UIKit/UIKit.h>
@interface WZXLOLCardLayout : UICollectionViewFlowLayout
@end
我们需要重写CollectionViewFlowLayout以下几个方法:
//这个用来传基本的数据 每次刷新第一步就是走这个方法
- (void)prepareLayout
//允许更新位置 你要是静态的话就不用重写了
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)oldBounds
//最重要的方法 返回当前矩形内所有的UICollectionViewLayoutAttributes
- (NSArray*)layoutAttributesForElementsInRect:(CGRect)rect
可能有人会对当前矩形不太理解,可以简单理解为collectionview在你当前屏幕的位置.
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
这个方法有些类似于scrollview的scrollViewWillEndDragging.
具体如下
#define GiveMeHeight(HEIGTH) (HEIGTH*[UIScreen mainScreen].bounds.size.height/736.0)
#define GiveMeWidth(WIDTH) (WIDTH*[UIScreen mainScreen].bounds.size.width/414.0)
//第一个要重写的方法 设置基本的大小
- (void)prepareLayout
{
//cell大小
self.itemSize = CGSizeMake(GiveMeWidth(300),GiveMeHeight(500));
//滑动方向
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
//组间四个方位间距
self.sectionInset = UIEdgeInsetsMake(200, 50.0, 200, 50.0);
//列间距
self.minimumLineSpacing = 0.0;
}
//允许更新位置
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)oldBounds
{
return YES;
}
//最大旋转角度
#define rotate 35.0*M_PI/180.0
//返回一个rect位置下所有cell的位置数组
- (NSArray*)layoutAttributesForElementsInRect:(CGRect)rect
{
//得到所有的UICollectionViewLayoutAttributes
NSArray* array = [super layoutAttributesForElementsInRect:rect];
CGRect visibleRect;
visibleRect.origin = self.collectionView.contentOffset;
visibleRect.size = self.collectionView.bounds.size;
for (UICollectionViewLayoutAttributes* attributes in array) {
//cell中心离collectionview中心的位移
//CGRectGetMidX表示得到一个frame中心点的X坐标
CGFloat distance = CGRectGetMidX(visibleRect) - attributes.center.x;
//CGRectIntersectsRect 判断两个矩形是否相交
//这里判断当前这个cell在不在rect矩形里
if (CGRectIntersectsRect(attributes.frame, rect))
{
CGFloat normalizedDistance = distance / ACTIVE_DISTANCE;
//ABS 绝对值
//如果位移小于一个过程所需的位移
if (ABS(distance) < ACTIVE_DISTANCE)
{
//normalizedDistance 当前位移比上完成一个过程所需位移 得到不完全过程的旋转角度
CGFloat zoom = rotate*normalizedDistance;
CATransform3D transfrom = CATransform3DIdentity;
transfrom.m34 = 1.0 / 600;
transfrom = CATransform3DRotate(transfrom, -zoom, 0.0f, 1.0f, 0.0f);
attributes.transform3D = transfrom;
attributes.zIndex = 1;
}
else
{
CATransform3D transfrom = CATransform3DIdentity;
transfrom.m34 = 1.0 / 600;
//向右滑
if (distance>0)
{
transfrom = CATransform3DRotate(transfrom, -rotate, 0.0f, 1.0f, 0.0f);
}
//向左滑
else
{
transfrom = CATransform3DRotate(transfrom, rotate, 0.0f, 1.0f, 0.0f);
}
attributes.transform3D = transfrom;
attributes.zIndex = 1;
}
}
}
return array;
}
//类似于scrollview的scrollViewWillEndDragging
//proposedContentOffset是没有对齐到网格时本来应该停下的位置
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
CGFloat offsetAdjustment = MAXFLOAT;
//CGRectGetWidth: 返回矩形的宽度
CGFloat horizontalCenter = proposedContentOffset.x + (CGRectGetWidth(self.collectionView.bounds) / 2.0);
//当前rect
CGRect targetRect = CGRectMake(proposedContentOffset.x, 0, self.collectionView.bounds.size.width, self.collectionView.bounds.size.height);
NSArray* array = [super layoutAttributesForElementsInRect:targetRect];
//对当前屏幕中的UICollectionViewLayoutAttributes逐个与屏幕中心进行比较,找出最接近中心的一个
for (UICollectionViewLayoutAttributes* layoutAttributes in array)
{
CGFloat itemHorizontalCenter = layoutAttributes.center.x;
if (ABS(itemHorizontalCenter - horizontalCenter) < ABS(offsetAdjustment))
{
//与中心的位移差
offsetAdjustment = itemHorizontalCenter - horizontalCenter;
}
}
//返回修改后停下的位置
return CGPointMake(proposedContentOffset.x + offsetAdjustment, proposedContentOffset.y);
}
接下来就只要在创建CollectionView的时候使用就行了:
WZXLOLCardLayout * flowLayout = [[WZXLOLCardLayout alloc]init];
_cardView = ({
UICollectionView * collectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) collectionViewLayout:flowLayout];
collectionView.delegate = self;
collectionView.dataSource = self;
//提前注册
[collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"];
collectionView;
});
[self.view addSubview:_cardView];
完整代码