iOS开发资料收集区iOS DeveloperiOS动画

UICollectionView实现放大缩小动画效果的左右滑动

2017-09-04  本文已影响997人  LDYG14

公司目前做一个需要左右滑动放大缩小功能的实现, 在此记录一下.


效果显示图.png

在利用UICollectionView来展示,那就需要自定义UICollectionViewFlowLayout

在整个实现过程中, 存在几个关键的问题点:

  1. 如何根据两个item之间的间距,在滑动过程中实现放大缩小的比例值?
  2. 当手停止拖拽时, 如何让UICollectionView定位显示离中心点最近的一个item?
  3. 如何根据随之定位的item位置, 改动对应下方/上方位置的内容?

问题一:根据两个item之间的间距,在滑动过程中实现放大缩小的比例值

计算放大缩小比例.png

核心在于: 计算UICollectionView中的centerX 的值与显示在屏幕上的每个item的centerX之间的差值

问题二:当手停止拖拽时, 如何让UICollectionView定位显示离中心点最近的一个item

定位距离中心点最近的item.png

上述截图中的方法

在滚动过程中图片的间距和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
上一篇下一篇

猜你喜欢

热点阅读