UICollectionView实现放大缩小动画效果的左右滑动
公司目前做一个需要左右滑动放大缩小功能的实现, 在此记录一下.
效果显示图.png
在利用UICollectionView来展示,那就需要自定义UICollectionViewFlowLayout
在整个实现过程中, 存在几个关键的问题点:
- 如何根据两个item之间的间距,在滑动过程中实现放大缩小的比例值?
- 当手停止拖拽时, 如何让UICollectionView定位显示离中心点最近的一个item?
- 如何根据随之定位的item位置, 改动对应下方/上方位置的内容?
问题一:根据两个item之间的间距,在滑动过程中实现放大缩小的比例值
计算放大缩小比例.png核心在于: 计算UICollectionView中的centerX 的值与显示在屏幕上的每个item的centerX之间的差值
问题二:当手停止拖拽时, 如何让UICollectionView定位显示离中心点最近的一个item
定位距离中心点最近的item.png上述截图中的方法
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity 用于 控制显示最终区域
--------proposedContentOffset 就是UICollectionView当前的偏移量
核心在于: 计算UICollectionView中的centerX的值与显示在屏幕上的每个item比较距离大小找到最小的间距值
在滚动过程中图片的间距和item的宽和高是动态计算变化的
cell宽高和间距.png图解:
计算距离中心点的间距.png
问题三:根据随之定位的item位置, 改动对应下方/上方位置的内容
监听scrollview的滚动.png 处理scrollview的滚动.png 处理滚动停止操作.png核心处理: 在判断滚动的距离值 = item的宽度 + 两个item之间的间距
285 = 235(Width) + 50(间距)
间距计算: 记录起始点与结束点.
注意: 这里在手动拖拽还为完全静止时设置scrollview不能滚动
原因在于: 如果在还未停止时就继续手动拖拽的话就导致计算的偏移量不准确,从而造成对应的内容对不上.
最后需要在完全静止时,将scrollview的滚动设置回正常情况.
到此实现左右切换item时放大缩小效果完成 !!
附上自定义layout文件中的代码
"#import "FIDCollectionViewFlowLayout.h"
//居中卡片宽度与据屏幕宽度比例
static float CardWidthScale = 0.63f;
static float CardHeightScale = 1.0f;
@implementation FIDCollectionViewFlowLayout
初始化方法
- (void)prepareLayout {
[super prepareLayout];
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
self.sectionInset = UIEdgeInsetsMake(0, [self collectionInset], 0, [self collectionInset]);
}
设置缩放动画
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
//扩大控制范围,防止出现闪屏现象
CGRect bigRect = rect;
bigRect.size.width = rect.size.width + 2*[self cellWidth];
bigRect.origin.x = rect.origin.x - [self cellWidth];
NSArray *arr = [self getCopyOfAttributes:[super layoutAttributesForElementsInRect:bigRect]];
//屏幕中线
CGFloat centerX = self.collectionView.contentOffset.x + self.collectionView.bounds.size.width/2.0f;
//刷新cell缩放
for (UICollectionViewLayoutAttributes *attributes in arr) {
CGFloat distance = fabs(attributes.center.x - centerX);
//移动的距离和屏幕宽度的的比例
CGFloat apartScale = distance/self.collectionView.bounds.size.width;
//把卡片移动范围固定到 -π/4到 +π/4这一个范围内
CGFloat scale = fabs(cos(apartScale * M_PI/4));
//设置cell的缩放 按照余弦函数曲线 越居中越趋近于1
attributes.transform = CGAffineTransformMakeScale(scale, scale);
}
return arr;
}
pragma mark 配置方法
卡片宽度
- (CGFloat)cellWidth {
return self.collectionView.bounds.size.width * CardWidthScale;
}
卡片间隔
- (float)cellMargin {
return (self.collectionView.bounds.size.width - [self cellWidth])/7;
}
设置左右缩进
- (CGFloat)collectionInset {
return self.collectionView.bounds.size.width/2.0f - [self cellWidth]/2.0f;
}
pragma mark 约束设定
//最小纵向间距
- (CGFloat)minimumLineSpacing {
return [self cellMargin];
}
//cell大小
- (CGSize)itemSize {
return CGSizeMake([self cellWidth],self.collectionView.bounds.size.height * CardHeightScale);
}
pragma mark 其他设定
//是否实时刷新布局
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
return true;
}
//防止报错 先复制attributes
- (NSArray *)getCopyOfAttributes:(NSArray *)attributes {
NSMutableArray *copyArr = [NSMutableArray new];
for (UICollectionViewLayoutAttributes *attribute in attributes) {
[copyArr addObject:[attribute copy]];
}
return copyArr;
}
// 控制显示最终区域
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
CGRect visableRect = CGRectMake(proposedContentOffset.x, 0,self.collectionView.width , self.collectionView.height);
// 中心轴x
CGFloat centerX = proposedContentOffset.x + self.collectionView.width * 0.5;
NSArray *attrArr = [super layoutAttributesForElementsInRect:visableRect];
CGFloat minDelta = MAXFLOAT;
for (UICollectionViewLayoutAttributes *attr in attrArr) {
CGFloat delta = fabs(attr.center.x - centerX);
if (delta < fabs(minDelta)) {
minDelta = attr.center.x - centerX;
}
}
proposedContentOffset.x += minDelta;
if (proposedContentOffset.x <= 0) {
proposedContentOffset.x = 0;
}
return proposedContentOffset;
}
@end
参考链接:
http://blog.csdn.net/u013282507/article/details/54136812
http://blog.csdn.net/u013282507/article/details/53103816
欢迎指正!
毛姆说的,阅读能为自己筑起一个避难所,几乎可以避开生命中所有的灾难。
欢迎关注我的微信公众号:LDYG2017, 或扫描下方二维码关注. 这里会分享我的读书笔记, 愿你我共同进步.
初始化蒲公英.jpg