美文网首页
UICollectionView自定义布局(二)

UICollectionView自定义布局(二)

作者: _誌念 | 来源:发表于2017-11-06 13:56 被阅读85次

    这是UICollectionView自定义布局的第二篇,实现类似UltravisualApp的视差效果,同样这篇文章的教程来自Ray家的Swift Expanding Cells in iOS Collection Views这篇文章。

    最终效果.gif

    自定义布局

    将该动画分解,首先实现如下图所示的效果。

    初始效果.gif

    随着CollectionView的滑动,itermCellframe的变化如下图所示:


    itermCell分为三种类型:
    1. FeaturedCell : 突出显示的cell,高度为featuredHeight
    2. StandardCell : 标准状态下的cell,高度为standardHeight
    3. ChangedCell : 高度随着contentOffSet改变而改变的cell,高度的变化范围在standardHeight和featuredHeight之间。(FeaturedCell下面的那个cell)
    1.获取FeaturedCell的索引
    - (int)featuredItemIndex{
       int index = (int)(self.collectionView.contentOffset.y / self.dragOffset);
       return MAX(0, index);
    }
    

    self.dragOffset是拖拽距离(当偏移量大于这个值时,featuredItemIndex的索引会变为下一个)。由当前FeaturedCell的索引index可以获得ChangedCell的索引为index+1,进而得到其他的索引位置就是StandardCell

    2.重写prepareLayout方法

    随着collectionView的滑动,standardCell 变化为 featuredCell,变化范围为[0 ,1]。

    - (CGFloat)nextItemPercentageOffset{
        CGFloat percent = (self.collectionView.contentOffset.y / self.dragOffset) - [self featuredItemIndex];
        return percent;
    }
    
    1. attribute.zIndex的值随着iterm的增加逐渐增大,形成上图所示的覆盖效果。
    2. ChangedCell的高度随着偏移距离,由standardHeight变化为featuredHeight
    3. 从视觉上看由StandardCell变为FeaturedCell只移动了standardHeight的距离,但是实际上contentOffSet.y移动的距离大于这个值,实际上移动了self.dragOffset才能完成这个变换。
    4. 详细的代码如下所示。
    - (void)prepareLayout{
        [super prepareLayout];
        [self.attributesArray removeAllObjects];
        
        CGRect frame = CGRectZero;
        CGFloat y = 0;
        
        NSInteger numberOfIterm = [self.collectionView numberOfItemsInSection:0];
        for (int i = 0; i < numberOfIterm; i++) {
            NSIndexPath *path = [NSIndexPath indexPathForItem:i inSection:0];
            UICollectionViewLayoutAttributes *attribute = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:path];
            /*下一个cell都在之前的cell之上*/
            attribute.zIndex = path.item;
            /*初始化时设置cell的高度都为标准高度*/
            CGFloat height = standardHeight;
            
            if (path.item == [self featuredItemIndex]) {
                /*featured Cell*/
                CGFloat yOffSet = standardHeight * [self nextItemPercentageOffset];
                y = self.collectionView.contentOffset.y - yOffSet;
                height = featuredHeight;
                
            }else if (path.item == [self featuredItemIndex] + 1 && path.item != numberOfIterm){
                /*在featuredCell之下,随着用户滚动逐渐变大*/
                CGFloat maxY = y + standardHeight;
                height = standardHeight + MAX((featuredHeight - standardHeight) * [self nextItemPercentageOffset], 0);
                y = maxY - height;
            }
            frame = CGRectMake(0, y, CGRectGetWidth(self.collectionView.bounds), height);
            attribute.frame = frame;
            [self.attributesArray addObject:attribute];
            
            /*获取下一个cell的初始的Y值*/
            y = CGRectGetMaxY(frame);
        }
        
        //重新刷新collectionView,不然数据会错乱
        [self.collectionView reloadData];
    }
    
    3.改变滚动停止时的位置

    ItermCell滚动的时候,将其停在固定的点。使其滚动停止时,屏幕显示的第一个cell永远是FeaturedCell

    - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity{
        NSInteger currentFeaturedIndex = round(proposedContentOffset.y / self.dragOffset);
        CGFloat yOffSet = currentFeaturedIndex * self.dragOffset;
        return CGPointMake(0, yOffSet);
    }
    

    添加图片背景和详情内容

    图片和文本的创建代码比较简单就不列出了,需要注意的是:

    1. UIImageViewcontentMode设置为UIViewContentModeScaleAspectFill。并且设置layer.masksToBounds = YES
    2. 一定要使用自动布局否则会显示不正常。

    重写applyLayoutAttributes

    1. 根据偏移量改变黑色CoverView的背景色,突出显示FeaturedCell
    2. 根据偏移量对titleLabel进行仿射变换。
    3. 根据偏移量对detailLabel进行透明度变化,只有当前cell是FeaturedCell的时候才显示。
    - (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes{
        [super applyLayoutAttributes:layoutAttributes];
    
        CGFloat standardHeight = 100.0;
        CGFloat featuredHeight = 280.0;
    
        /*根据移动距离改变CoverView透明度*/
        CGFloat factor = 1 - (featuredHeight - CGRectGetHeight(layoutAttributes.frame))/(featuredHeight - standardHeight);
        CGFloat minAlpha = 0.2;
        CGFloat maxAlpha = 0.75;
        CGFloat currentAlpha = maxAlpha - (maxAlpha - minAlpha) * factor;
        self.coverView.alpha = currentAlpha;
        
        /*改变字体大小*/
        CGFloat titleScale = MAX(0.5, factor);
        self.titleLabel.transform = CGAffineTransformMakeScale(titleScale, titleScale);
        
        /*设置detailLabel的透明度*/
        self.timeAndRoomLabel.alpha = factor;
        self.speakerLabel.alpha = factor;
    }
    

    至此,自定义布局就全部完成了,Demo链接可以到GitHub下载

    相关文章

      网友评论

          本文标题:UICollectionView自定义布局(二)

          本文链接:https://www.haomeiwen.com/subject/scefmxtx.html