简介
- 效果显示
在显示的图片中,最中间的图片为我们要查看图片,是最大的,然后两边的图片比较小,随着我们的拖动,越靠近中间位置,图片越大 - 实现思路
使用UICollectionView来显示图片,采用流水布局flowLayout,但是普通的流水布局显然满足不了我们的需求,所以说,我们自定义一个flowLayout来实现我们的需求
自定义流水布局
自定义类CLHFlowLayout
继承于 UICollectionViewFlowLayout
要实现我们想要的效果,只要重写三个方法
- 处理全部的布局所需对象
这个方法返回的是我们设置的布局所需要的所有的对象,所以说,我们在这里把我们图片的缩放设置好
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
NSArray *attributeArray = [super layoutAttributesForElementsInRect:rect];
for (UICollectionViewLayoutAttributes *attribute in attributeArray) {
//计算与中心点之间的距离
CGFloat disWithCenter = fabs((attribute.center.x - self.collectionView.contentOffset.x) - self.collectionView.bounds.size.width * 0.5);
//确定缩放比例
CGFloat scale = 1 - disWithCenter / (self.collectionView.bounds.size.width * 0.5) * 0.25;
attribute.transform = CGAffineTransformMakeScale(scale, scale);
}
return attributeArray;
}
中心点距离计算公式:
红色:我们所要求的距离
蓝色:collectionView的偏移量的x值(self.collectionView.contentOffset.x)
黄色:cell中心点的坐标x值(attribute.center.x)
黑色:collectionView的一半长度(self.collectionView.bounds.size.width * 0.5)
所以说红色 = (黑色 - (黄色 - 蓝色)),即为代码中我们所求
- 滑动停止处理细节
参数分析:1.proposedContentOffset:collectionView停止滚动时的位置,2.velocity:速率,3.返回值:自定义要停止的位置
因为有可能滑动停止的时候,中间并没有图片(如图所示),因为如果我们手指滑动的很快的时候,滚动会有一个惯性,这个我们没法控制,所以说我们要找出距离中心点最近的那个cell,然后偏移collectionView,使那个cell为中心的图片。
//获取当前偏移量
CGPoint targetProposed = [super targetContentOffsetForProposedContentOffset:proposedContentOffset withScrollingVelocity:velocity];
//获取当前可视范围内显示的cell
NSArray *attributeArray = [super layoutAttributesForElementsInRect:CGRectMake(targetProposed.x, 0, self.collectionView.bounds.size.width, MAXFLOAT)];
//寻找距离中心点最近的图片
CGFloat minDis = MAXFLOAT;
for (UICollectionViewLayoutAttributes *attr in attributeArray) {
CGFloat disWithCenter = (attr.center.x - targetProposed.x) - self.collectionView.bounds.size.width * 0.5;
if(fabs(disWithCenter) < fabs(minDis)){
minDis = disWithCenter;
}
}
//停止滚动后可能没有图片在中间,所以我们要计算距离中间最近的图片,然后偏移过去
targetProposed.x += minDis;
if(targetProposed.x < 0){
targetProposed.x = 0;
}
return targetProposed;
- 当bounds发生改变的时候重新布局
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{
return YES;
}
这就大功告成啦,当我们使用的时候,直接将当前布局设置为UIColectionView的布局就行啦。
Demo地址:https://github.com/AnICoo1/ImageViewScroll