iOS 滚动放大缩小

iOS 滚动放大缩小_第1张图片
滚动放大缩小.gif

简介##

效果:滚动到中间的时候最大,距离中间越远越小.
思路:实现这样的效果,我们首先要选对UI组件,这里我选择使用UICollectionView,而它的布局主要是依靠其flowLayout,所以我决定自定义FlowLayout实现该效果.

步骤##

自定义WYCollectionViewFlowLayout继承自UICollectionViewFlowLayout重写3个布局方法

@interface WYCollectionViewFlowLayout : UICollectionViewFlowLayout

@end

@implementation WYCollectionViewFlowLayout

// 这个方法返回所有的布局所需对象,瀑布流也可以重写这个方法实现.
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
    // 1.获取cell对应的attributes对象
    NSArray *arrayAttrs = [super layoutAttributesForElementsInRect:rect];
    
    // 2.计算整体的中心点的x值
    CGFloat centerX = self.collectionView.contentOffset.x + self.collectionView.bounds.size.width * 0.5;
    
    // 3.修改一下attributes对象
    for (UICollectionViewLayoutAttributes *attr in arrayAttrs) {
        // 3.1 计算每个cell的中心点距离
        CGFloat distance = ABS(attr.center.x - centerX);
        
        // 3.2 距离越大,缩放比越小,距离越小,缩放比越大
        CGFloat factor = 0.003;
        CGFloat scale = 1 / (1 + distance * factor);
        attr.transform = CGAffineTransformMakeScale(scale, scale);
    }
    return arrayAttrs;
}

// 当bounds发生改变的时候需要重新布局
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
    return true;
}

/// 滑动停止
///
/// @param proposedContentOffset 当手指滚动完毕后,自然情况下根据“惯性”,会停留的位置
/// @param velocity              速率,周率
///
/// @return 人为要让它停留的位置
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity {
    // 1.计算中心点位置
    CGFloat centerX = proposedContentOffset.x + self.collectionView.bounds.size.width * 0.5;
    
    // 2.计算可视化区域
    CGFloat visibleX = proposedContentOffset.x;
    CGFloat visibleY = proposedContentOffset.y;
    CGFloat visibleW = APP_WIDTH;
    CGFloat visibleH = self.collectionView.bounds.size.height;
    CGRect visibleRect = CGRectMake(visibleX, visibleY, visibleW, visibleH);
    
    // 3.获取可视区域的cell的attribute对象
    NSArray *attrs = [self layoutAttributesForElementsInRect:visibleRect];
    
    // 4.比较出最小的偏移
    int min_idx = 0;
    UICollectionViewLayoutAttributes *min_attr = attrs[min_idx];
    
    // 5.循环比较出最小的
    for (int i = 1; i< attrs.count; i++){
        // 5.1min_attr和中心点的距离
        CGFloat distance1 = ABS(min_attr.center.x - centerX);
        
        // 5.2当前循环的attr和中心点的距离
        UICollectionViewLayoutAttributes *currentAttr = attrs[i];
        CGFloat distance2 = ABS(currentAttr.center.x - centerX);
        
        if (distance2 < distance1) {
            min_idx = i;
            min_attr = currentAttr;
        }
    }
    // 6.计算出最小的偏移值
    CGFloat offsetX = min_attr.center.x - centerX;
    
    return CGPointMake(proposedContentOffset.x + offsetX, proposedContentOffset.y);
}

@end

然后在初始化UICollectionView的时候,设置其流水布局collectionViewLayout为我们自定义的WYCollectionViewFlowLayout即可实现滚动的放大缩小了.

你可能感兴趣的:(iOS 滚动放大缩小)