Collectionview自定义单元格布局/行为

时间:2016-08-04 12:58:34

标签: ios objective-c swift uicollectionview

我正在使用一个水平滑动的集合视图,并试图对单元格进行自定义布局,类似于iphone“app close”。我不知道如何实现这样的效果,或者从哪里开始,所以我希望得到一些指示。 我非常擅长解释自己,所以我试图说明所需的效果,从它现在的表现,到它应该如何表现。

提前致谢!

enter image description here

1 个答案:

答案 0 :(得分:3)

我已经使用了类似的视图。这是我项目的github linkThis is the screenshot of the view 您的要求与我的观点之间的唯一区别是您还需要缩放左侧单元格。为了实现这个观点,我遇到了两个主要问题:

1)当两个单元格(左侧单元格和右侧单元格)同样暴露时,完全停止滚动,因为我在CollectionView.m文件中包含以下代码。

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
    float pageWidth = 240; // width + space

    float currentOffset = scrollView.contentOffset.x;
    float targetOffset = targetContentOffset->x;
    float newTargetOffset = 0;

    if (targetOffset > currentOffset)
        newTargetOffset = ceilf(currentOffset / pageWidth) * pageWidth;
    else
        newTargetOffset = floorf(currentOffset / pageWidth) * pageWidth;

    if (newTargetOffset < 0)
        newTargetOffset = 0;
    else if (newTargetOffset > scrollView.contentSize.width)
        newTargetOffset = scrollView.contentSize.width;

    targetContentOffset->x = currentOffset;
    [scrollView setContentOffset:CGPointMake(newTargetOffset, 0) animated:YES];

    int index = newTargetOffset / pageWidth;

    if (index == 0) { // If first index
        CollectionViewCell *cell =(CollectionViewCell *) [self cellForItemAtIndexPath:[NSIndexPath indexPathForItem:index  inSection:0]];
        cell.transform = CGAffineTransformIdentity;
        cell = (CollectionViewCell *)[self cellForItemAtIndexPath:[NSIndexPath indexPathForItem:index + 1  inSection:0]];
        //cell.transform = TRANSFORM_CELL_VALUE;

    }else{
        CollectionViewCell *cell =(CollectionViewCell *)[self cellForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]];
        //cell.transform = CGAffineTransformIdentity;

        index --; // left
        cell =(CollectionViewCell *)[self cellForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]];
          //  cell.transform = TRANSFORM_CELL_VALUE;
        index ++;
        index ++; // right
        cell = (CollectionViewCell *)[self cellForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]];
        //cell.transform = TRANSFORM_CELL_VALUE;
    }
} 

2)其次,您需要为单元格提供适当的约束以达到要求,因为我使用了 UICollectionViewFlowLayout 类。 在此,我为可见细胞提供了适当的约束。 FlowLayout代码如下所示:

#import "CollectionLayout.h"


@implementation CollectionLayout
{
    NSIndexPath *mainIndexPath;
}

-(void)prepareLayout{
    [super prepareLayout];
}

-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
     UICollectionViewLayoutAttributes *attributes = [[super layoutAttributesForItemAtIndexPath:indexPath] copy];
    CATransform3D theTransform = CATransform3DIdentity;
    const CGFloat theScale = 1.05f;
    theTransform = CATransform3DScale(theTransform, theScale, theScale, 1.0f);
    attributes.transform3D=theTransform;
    return attributes;
}

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
    return YES;
}

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{
    NSArray *attributesSuper = [super layoutAttributesForElementsInRect:rect];
    NSArray *attributes = [[NSArray alloc]initWithArray:attributesSuper copyItems:YES];
    NSArray *cellIndices = [self.collectionView indexPathsForVisibleItems];
    NSIndexPath *neededIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
    for(NSInteger i=0;i<cellIndices.count;i++){
        NSIndexPath *indexPath = [cellIndices objectAtIndex:i];
        if(indexPath.row>neededIndexPath.row){
            neededIndexPath=indexPath;
        }
        NSLog(@"%ld,%ld",(long)indexPath.row,(long)indexPath.section);
    }
    if(cellIndices.count==0){
        mainIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
    }else{
        if(neededIndexPath.row>0)
            mainIndexPath = [NSIndexPath indexPathForRow:neededIndexPath.row-1 inSection:0];
    }

    for (UICollectionViewLayoutAttributes *attribute in attributes)
    {
        [self applyTransformToLayoutAttributes:attribute];
    }
    return attributes;
}

-(void) applyTransformToLayoutAttributes:(UICollectionViewLayoutAttributes *)attribute{
    if(attribute.indexPath.row == mainIndexPath.row){
        attribute.size = CGSizeMake(self.collectionView.bounds.size.width-40, self.collectionView.bounds.size.height);
        attribute.zIndex+=10;
    }
}

#pragma mark - Transform related

@end

从我的github链接克隆项目后,您将很容易理解我所做的事情,并且您可以编写自己的代码来实现您的视图。您只需要在代码的这一部分中提供约束。 您还需要为每个单元格正确调整zIndex

 -(void) applyTransformToLayoutAttributes:(UICollectionViewLayoutAttributes *)attribute{
        if(attribute.indexPath.row == mainIndexPath.row){
            attribute.size = CGSizeMake(self.collectionView.bounds.size.width-40, self.collectionView.bounds.size.height);
            attribute.zIndex+=10;
        }
    }

我希望你明白我的观点。

注意:我仅在iPhone 5s上测试了github代码,您可能需要为其他设备稍微调整一下。