最常见的是网上有很多商城中的瀑布流列表展示和高大上图片浏览中会用到自定义的UICollectionViewFlowLayout,前者是屏幕上根据需求展示不同大小的UICollectionViewCell两列或者三列,错落排列,后者是展现出一种图片立体环绕视觉,前方图片总是居中显示,两侧图片比例要小,随着显现或者消失做放大或者缩小处理
最近,在实际项目中遇到一种类似后者图片浏览的那种效果,但是每个UICollectionViewCell等大显示,不做放大缩小处理。因为之前了解过这种效果实现的大概机制,所以,开始以为会比较简单,可以后来发现自己错了,我先从网上找了demo,贴一下主要代码,每个方法的作用我都加了备注
//重新设置collectionView的contentOffset,也就是每个cell的x值,proposedContentOffset是实际按照设置的layout布局的偏移量,该方法重新设置实际需要的偏移量,当然要根据collectionView的宽度,layout设置的itemSize以及sectionInsets等
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
proposedContentOffset.y = 0.0;
if (_isPagingEnabled) {
proposedContentOffset.x = [self PageMove:proposedContentOffset];
}else{
proposedContentOffset.x = [self SMove:proposedContentOffset velocity:velocity];
}
return proposedContentOffset;
}
//内部参数根据自己实际需要设置,这就需要你的知识了
-(CGFloat)PageMove:(CGPoint)proposedContentOffset{
CGFloat set_x = proposedContentOffset.x;
if (set_x > _move_x) {
_move_x += SCREENWITH - 15 * 2;
}else if(set_x < _move_x){
_move_x -= SCREENWITH - 15 * 2;
}
set_x = _move_x;
return set_x;
}
-(CGFloat)SMove:(CGPoint)proposedContentOffset velocity :(CGPoint)velocity{
CGFloat offSetAdjustment = MAXFLOAT;
CGFloat horizontalCenter = (CGFloat) (proposedContentOffset.x + (self.collectionView.bounds.size.width / 2.0));
CGRect targetRect = CGRectMake(proposedContentOffset.x, 0.0, self.collectionView.bounds.size.width, self.collectionView.bounds.size.height);
NSArray *array = [self layoutAttributesForElementsInRect:targetRect];
UICollectionViewLayoutAttributes *currentAttributes;
for (UICollectionViewLayoutAttributes *layoutAttributes in array)
{
if(layoutAttributes.representedElementCategory == UICollectionElementCategoryCell)
{
CGFloat itemHorizontalCenter = layoutAttributes.center.x;
if (ABS(itemHorizontalCenter - horizontalCenter) < ABS(offSetAdjustment))
{
currentAttributes = layoutAttributes;
offSetAdjustment = itemHorizontalCenter - horizontalCenter;
}
}
}
CGFloat nextOffset = proposedContentOffset.x + offSetAdjustment;
proposedContentOffset.x = nextOffset;
CGFloat deltaX = proposedContentOffset.x - self.collectionView.contentOffset.x;
CGFloat velX = velocity.x;
if(deltaX == 0.0 || velX == 0 || (velX > 0.0 && deltaX > 0.0) || (velX < 0.0 && deltaX < 0.0)) {
} else if(velocity.x > 0.0) {
for (UICollectionViewLayoutAttributes *layoutAttributes in array)
{
if(layoutAttributes.representedElementCategory == UICollectionElementCategoryCell)
{
CGFloat itemHorizontalCenter = layoutAttributes.center.x;
if (itemHorizontalCenter > proposedContentOffset.x) {
proposedContentOffset.x = nextOffset + (currentAttributes.frame.size.width / 2) + (layoutAttributes.frame.size.width / 2);
break;
}
}
}
} else if(velocity.x <= 0.0) {
for (UICollectionViewLayoutAttributes *layoutAttributes in array)
{
if(layoutAttributes.representedElementCategory == UICollectionElementCategoryCell)
{
CGFloat itemHorizontalCenter = layoutAttributes.center.x;
if (itemHorizontalCenter > proposedContentOffset.x) {
proposedContentOffset.x = nextOffset - ((currentAttributes.frame.size.width / 2) + (layoutAttributes.frame.size.width / 2));
break;
}
}
}
}
if (proposedContentOffset.x == -0.0) {
proposedContentOffset.x = 0.0;
}
return proposedContentOffset.x;
}
-(void)setPagingEnabled:(BOOL)isPagingEnabled{
_isPagingEnabled = isPagingEnabled;
}
static CGFloat const ActiveDistance = 350;
static CGFloat const ScaleFactor = 0.05;
//重写该方法,返回需要的每个Cell的布局,在系统的基础上做出需要的效果,这里就用大了放大缩小
-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray *array = [super layoutAttributesForElementsInRect:rect];
// CGRect visibleRect;
// visibleRect.origin = self.collectionView.contentOffset;
// visibleRect.size = self.collectionView.bounds.size;
//
// for (UICollectionViewLayoutAttributes* attributes in array) {
// CGFloat distance = CGRectGetMidX(visibleRect) - attributes.center.x;
// CGFloat normalizedDistance = distance / ActiveDistance;
// CGFloat zoom = 1 + ScaleFactor*(1 - ABS(normalizedDistance));
// attributes.transform3D = CATransform3DMakeScale(1.0, zoom, 1.0);
// attributes.zIndex = 1;
// }
return array;
}
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
}
如上代码,我开始只是把放大缩小的效果注释了,其实这个方法可以不要,因为我不需要对cell做特殊处理,我以为居中显示且没有放大缩小,可是偏移量根本不是我想要的,为什么,因为- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity是需要根据自己设置的collectionView的宽度和itemSize等变量自己去计算这个偏移量的
我貌似在说废话。。。