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

标签 ios objective-c swift uicollectionview

我正在使用一个collectionview,它水平滑动,并尝试对单元格进行自定义布局,类似于iphone的“应用程序关闭器”。我不知道如何实现这样的效果,或者从哪里开始,所以我希望得到一些指示。 我很不擅长解释自己,所以我尝试说明所需的效果,从它现在的行为方式,直到它应该如何行为。

提前致谢!

enter image description here

最佳答案

我曾经使用过类似的 View 。这是 github link我的项目。 This 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 链接克隆该项目,您将轻松理解我所做的事情,并且您可以编写自己的代码来实现您的 View 。您只需要在这部分代码中提供您的约束。 您还需要正确调整每个单元格的 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 代码,您可能需要针对其他设备进行一些调整。

关于ios - Collectionview 自定义单元格布局/行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38768039/

相关文章:

ios - Swift - 桥接 header 编译器错误

swift - 'on' 在 Swift 中是什么意思?

iphone - View 出现在键盘窗口上。如何解决

ios - 无法使用 Visual Studio Tools for Cordova 部署到 iPad Pro(更新 10)

ios - Swift - 循环中的完成处理程序

ios - 如何向 UITableViewCell 添加自定义分隔符?

ios - 从 Swift 4 的文件目录中删除用户选择的文件?

iOS Facebook 如何获得推荐好友,例如 Hangtime 或 DrinkAdvisor

ios - 核心数据一对多关系核心数据生成的访问器

ios - 在 iOS 中将项目添加到阅读列表