【问题标题】:Collectionview custom cell layout/behaviourCollectionview 自定义单元格布局/行为
【发布时间】:2016-08-04 12:58:33
【问题描述】:

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

提前致谢!

【问题讨论】:

  • 我想你应该看看这里显示的例子github.com/nicklockwood/iCarousel,在这里你会发现很多类型的效果,然后你至少会知道如何开始和做什么
  • 非常感谢!这看起来像是自定义效果的完全正确的引擎。

标签: ios objective-c swift uicollectionview


【解决方案1】:

我曾使用过类似的视图。这是我项目的 github link 您的要求和我的观点之间的唯一区别是您也需要缩放左侧单元格。为了实现这个观点,我遇到了两个主要问题:

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 代码,您可能需要针对其他设备稍作调整。

【讨论】:

  • 非常感谢!这是一个很好的灵感,我设法做了我自己的变种,它的工作方式与预期完全一样。这是伟大的工作!
猜你喜欢
  • 1970-01-01
  • 2013-10-26
  • 2017-05-07
  • 1970-01-01
  • 1970-01-01
  • 2015-03-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多