【问题标题】:Creating a custom collection view layout创建自定义集合视图布局
【发布时间】:2014-08-11 22:28:35
【问题描述】:

我正在尝试创建一个如下图所示的集合视图。中心项目将始终具有“焦点”并且更大,这有点像封面流概念:

http://s13.postimg.org/n6vzil213/layout_schematic.png

我可以使用 UICollectionViewFlowLayout 来实现这一点,但我希望底部单元格 (3) 的动画效果更大,而中间单元格 (2) 的动画效果更小?我假设我需要对滚动视图委托方法进行一些数学运算。

知道如何实现这一目标吗?

【问题讨论】:

  • 需要是collection view吗?你能用 TableView 代替吗?
  • 是的,它应该是一个集合视图,表格视图不像集合视图那样提供动画功能。
  • 表格视图也有动画功能。您认为哪些动画是您不需要的?
  • 我宁愿让门打开一个集合视图,因为以后更换布局更容易,而且它们提供了更多的灵活性。
  • 我认为你使用 UITableView 还是 UICollectionView 并不重要。而且我认为您不需要(必然)使用 UICollectionViewLayout (或 UICollectionViewFlowLayout )来实现这一点。为什么不继承一些 UICollectionViewCells?

标签: ios objective-c uicollectionview uicollectionviewlayout


【解决方案1】:

您可以仅通过子类化 UICollectionViewFlowLayout 来做到这一点。

步骤如下:

  1. 创建 UICollectionViewFlowLayout 子类
  2. 覆盖 shouldInvalidateLayoutForBoundsChange: 并返回 YES
  3. 覆盖 layoutAttributesForElementsInRect: 和 layoutAttributesForItemAtIndexPath:。调用超级实现以获取标准 FlowLayout 值。
  4. 创建一个方法,由步骤#3 中的两个方法调用,它会根据项目与集合视图中心的距离来更改项目的布局属性。使用数学为项目设置正确的 itemSize / transform / 3D 变换。

这是一个超级粗略的示例,它可以满足您的需求,但没有正确的数学运算。

@implementation MMLayout

-(CGSize)itemSize
{
    return CGSizeMake(200.0f, 200.0f);
}

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

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSArray *attributes = [super layoutAttributesForElementsInRect:rect];

    for (UICollectionViewLayoutAttributes *atts in attributes) {
        [self scaleForPositionOfAttributes:atts];
    }

    return attributes;
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;
{
    UICollectionViewLayoutAttributes *atts = [super layoutAttributesForItemAtIndexPath:indexPath];

    [self scaleForPositionOfAttributes:atts];

    return atts;
}

- (void)scaleForPositionOfAttributes:(UICollectionViewLayoutAttributes *)attributes
{
    CGFloat collectionViewHeight = CGRectGetHeight(self.collectionView.bounds);
    CGFloat collectionViewCenter = collectionViewHeight / 2.0f;

    CGFloat scaleForCenter = ABS(collectionViewCenter - (attributes.frame.origin.y - self.collectionView.contentOffset.y)) < 50.0f ? 1.3f : 0.7f;
    attributes.size = CGSizeMake(200.0f * scaleForCenter, 200.0f * scaleForCenter);
}

@end

【讨论】:

  • 原来这并没有真正达到我想要的效果,我相信我想要的需要在collectionView的scrollViewDidScroll中完成:通过玩transforms?
  • 您也可以在此处执行此操作。单元格属性有 transform 和 3Dtransform。您可以通过访问 self.collectionview.contentoffset 来获取当前滚动位置。我没有计算出所有的变换/项目大小细节,但暗示你需要根据自己的喜好微调这方面。
  • 好吧,我试着让它工作,我确实让它更接近了,但我已经投入了大约 9 或 10 个小时,但我仍然无法到达那里。也许我会选择更简单的东西。
  • 我遇到了边缘情况(第一个和最后一个单元格)的问题。我的图表可能有点偏离。视图的第一个单元格应该是“焦点视图”,然后它应该是滚动时的中间单元格。此外,当尺寸增加时,它会与其他单元格重叠(事实证明我不能让它重叠)
  • 另外,我不知道是否可以对此进行动画处理,因为这是从小型单元格到大型单元格的艰难过渡?
猜你喜欢
  • 1970-01-01
  • 2016-01-21
  • 2017-05-22
  • 2015-06-12
  • 1970-01-01
  • 2016-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多