自定义UICollectionViewFlowLayout

闲着没事,无意间看到掌上英雄联盟查看皮肤中CollectionView的效果,觉得很不错,趁着机会也学习下UICollectionViewFlowLayout的自定义,先看效果:

查找资料,发现苹果提供了2个关于Layout的demo,

Apple demo下载

LineLayoutDemo下载

这个基本上就是复制LineLayout的学习,在原来的基础上优化了一点。

首先创建一个继承与UICollectionViewFlowLayout的类,
我的.h

@interface GLCollectionViewFlowLayou : UICollectionViewFlowLayout

实现文件中主要有四个方法:

//可以在此方法中初始化你的layout
- (void)prepareLayout {
    //必须调用super
    [super prepareLayout];
}
//在这里改变布局 滑动时会时时调用此方法
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
}
//替换最终滑动的contentOffset, proposedContentOffset是预期滑动停止的位置
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity {
}
// 当collectionView bounds改变时,是否重新布局
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
    return YES;
}

苹果的LineLayout在滑到第一个和最后一个的时候,有点问题,不能更新到正确的位置。

在设置layout的时候设置UICollectionView的_collectionView.contentInset,设置如下:

    CGFloat left = CGRectGetWidth(self.collectionView.frame) / 2 - flowLayout.itemSize.width / 2;
    _collectionView.contentInset = UIEdgeInsetsMake(0, left, 0, left);

customLayout.m中,在targetContentOffsetForProposedContentOffset方法中处理第一个和最后一个的返回的contentOffset:

 //替换希望的contentOffset
    CGPoint actualPoint = CGPointMake(proposedContentOffset.x + minDistance, proposedContentOffset.y);
    
    //处理第一个 和 最后一个的contentOffset
    CGFloat minContentOffsetX = -floor(self.collectionView.contentInset.left);
    CGFloat maxContentOffsetX = floor(self.collectionView.contentSize.width - CGRectGetWidth(self.collectionView.frame) + self.collectionView.contentInset.right);
    actualPoint = actualPoint.x < minContentOffsetX ? CGPointMake(minContentOffsetX, actualPoint.y) : actualPoint;
    actualPoint = actualPoint.x > maxContentOffsetX ? CGPointMake(maxContentOffsetX, actualPoint.y) : actualPoint;
    return actualPoint;

这样就OK了,滑倒第一个和最后一个也可以正常的显示和滚动了。

Demo地址:

点我哦


你可能感兴趣的:(自定义UICollectionViewFlowLayout)