UICollectionView自定义流水布局

2016-04-07  本文已影响485人  MarceauHe

UICollectionView的使用

如果要在滚动的时候改变cell,那么就要实现以下方法来设置cell的布局,系统的布局不能满足我们的要求,因此我们要自定义布局,并且在方法中一定要调用super父类的相应方法

方法一
/*
 方法一:

 返回cell布局,可以获取cell布局,直接操作cell尺寸
 作用:指定一段区域,就能返回这个区域内所有cell布局,可以一次性返回所有的布局
 */
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
    //拿到系统返回的所有的cell布局,对其进行修改,然后返回

    //获取已经显示出来的cell的布局
    NSArray *atts = [super layoutAttributesForElementsInRect:self.collectionView.bounds];

    //偏移量
    CGFloat offsetX = self.collectionView.contentOffset.x;
    CGFloat W = self.collectionView.bounds.size.width;

    for (UICollectionViewLayoutAttributes *cellAtt in atts) {
         //cell离中心点距离为marginToCenter(显示出来的cell的中心点X值减去CollectionView宽度的一半与CollectionView偏移量的和)
        //距离不能是负数,因此要取绝对值
        CGFloat marginToCenter = fabs(cellAtt.center.x - (offsetX + W * 0.5));

        //获取缩放比例
        CGFloat scale = 1 - marginToCenter / (0.5 * W) * 0.25;
        NSLog(@"%f",scale);

        //形变
        cellAtt.transform = CGAffineTransformMakeScale(scale, scale);
    }
    return atts;
}

方法二
/*
 方法二:

 Invalidate:刷新
 在滚动的时候是否刷新布局
 */
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
    //自己验证的是系统默认返回NO,也就是不允许在滚动的时候刷新,也就是下面的prepareLayout只会在collectionView第一次显示的时候调用,返回YES的时候,就会在滚动的时候不停的调用
//   return [super shouldInvalidateLayoutForBoundsChange:newBounds];

    return YES;
}
方法三
/*
 方法三:

作用:返回最终偏移量
调用时刻:当用户手指抬起时,拖动完成的时候就会调用
 */
-(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
    //最终偏移量 =? 手指抬起时候的偏移量collectionView的偏移量
    //慢慢拖,相等 ,如果很快的拖动,就不相等,这个是因为惯性,collectionView还要减速继续滚动到停止

     CGFloat W = self.collectionView.bounds.size.width;

    //获取最终显示的cell
    CGRect targetRect = CGRectMake(proposedContentOffset.x, 0, W, MAXFLOAT);

    //给定一个区域,获取最终显示的cell
     NSArray *atts = [super layoutAttributesForElementsInRect:targetRect];

    //遍历数组,获取cell中心点离collectionView最近的那个cell
    CGFloat minMargin = MAXFLOAT;

    for (UICollectionViewLayoutAttributes *cellAtt in atts) {

        CGFloat marginToCenter = cellAtt.center.x - (proposedContentOffset.x + W * 0.5);
        if (fabs(marginToCenter) < fabs(minMargin)) {

            minMargin = marginToCenter;
        }

    }
    proposedContentOffset.x += minMargin;
    NSLog(@"%f",proposedContentOffset.x);

    //如果在程序运行之后,将collectionView向左边移动一点点,会出现最终偏移量为-0的情况,要解决这个bug,就要写下面的代码,不让它的偏移量出现负数
    if (proposedContentOffset.x < 0) {
        proposedContentOffset.x = 0;
    }
    return proposedContentOffset;
}

方法四
/*
 方法四:

必须要调用[super prepareLayout]
作用:计算所有cell布局,前提条件,cell布局不会经常改变,是固定死
时刻:第一次要显示collectionView才会调用,每次collectionView刷新都会调用
 */
- (void)prepareLayout
{
    [super prepareLayout];
}
方法五
/*
 方法五:

返回滚动范围
 */
-(CGSize)collectionViewContentSize
{
    //返回0的时候什么都没有
//    return CGSizeZero;
   return [super collectionViewContentSize];
}
上一篇下一篇

猜你喜欢

热点阅读