美文网首页iOS技术交流收藏
collectionView 实现画廊效果

collectionView 实现画廊效果

作者: zx1798 | 来源:发表于2016-08-15 11:49 被阅读0次

    效果

    效果.png

    标题是collectionView,但其实这篇文章说的是自定义FlowLayout的事😄

    大家都知道collectionView关于元素的事情,更多是于布局决定的。

    比如滚动方向,元素间距,元素尺寸,布局的组间距,布局的行间距(这些都决定了元素的位置)。

    如果要实现画廊效果只需要关心三个方法

    /**
     *  当bounds发生改变(滚动就是改变了bounds,改变了可视区)的时候是否允许刷新布局。
     *
     *  @param newBounds 
     *
     *  @return 默认返会NO
     */
    - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
       return YES;
    }
    
    /**
     *  返回区域内的cell,这个方法做根据cell距离中心点 来缩放
     *
     *  @param rect 区域
     *
     *  @return 区域内的cell
     */
    - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
        //bounds的改变就是可视范围的改变, 那么我们去拿可视范围内的cell
        NSArray *attrs = [super layoutAttributesForElementsInRect:self.collectionView.bounds];
        
        //计算每一个cell与中心点的距离, 并通过cell与中心点距离的改变来缩放cell
        for (UICollectionViewLayoutAttributes *attr in attrs) {
            CGFloat delta = fabs((attr.center.x - self.collectionView.contentOffset.x) - self.collectionView.frame.size.width * 0.5);
            
            CGFloat scale = 1 - (delta / self.collectionView.bounds.size.width * 0.5) * 0.55;
            
            attr.transform = CGAffineTransformMakeScale(scale, scale);
        }
        
        return attrs;
    }
    
    /**
     *  计算最终的偏移量, 在这个方法里做判断最小距离自动滚动到中间效果
     *
     *  @param proposedContentOffset 预计偏移
     *  @param velocity              速率
     *
     *  @return 最终偏移
     */
    - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity {
        
        CGFloat collectionW = self.collectionView.bounds.size.width;
        CGFloat collectionH = self.collectionView.bounds.size.height;
        
    //    1确定最终的滚动位置
        CGPoint targetP = [super targetContentOffsetForProposedContentOffset:proposedContentOffset withScrollingVelocity:velocity];
    //    2利用滚动位置去拿当前显示的所有元素
        CGRect rect = CGRectMake(targetP.x, 0, collectionW, collectionH);
        NSArray<UICollectionViewLayoutAttributes *> *attrs = [super layoutAttributesForElementsInRect:rect];
        
    //    3获取所有滚动元素距离中心点的最小值
        CGFloat minDelta = MAXFLOAT;
        for (UICollectionViewLayoutAttributes *attr in attrs) {
            CGFloat delta = attr.center.x - targetP.x - collectionW * 0.5;
            
            if (fabs(delta) < fabs(minDelta))
                minDelta = delta;
        }
        
    //    4用最终的偏移量加最小值 形成自动滑动的效果
        targetP.x += minDelta;
        if (targetP.x < 0)
            targetP.x = 0;
            
        return targetP;
    }
    
    bounds
    bounds的origin是可以改变的,取决于有没有可视范围外的可滚动区域。
    scrollView的滚动是通过可视范围的改变(bounds)来实现滚动的。
    

    想要实现这个效果的朋友直接自定义FlowLayout,重写以上三个方法即可。

    相关文章

      网友评论

        本文标题:collectionView 实现画廊效果

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