如何获得UICollectionView的滚动精明背景

时间:2014-02-25 19:24:20

标签: ios ios7 uicollectionview

使用UICollectionViewController和我自己的UICollectionViewLayout子类,我将一个显示Gannt样式时间图的视图放在一起。使用该框架来完成乐队非常容易。

我不清楚如何设计提供时间背景的支持视图。我在Inkscape中勾画了一个例子:

Sample Time Series

黑色矩形轮廓是当前用户可能滚动到的位置的示例。

所以,我得到了如何做粉色/橙色/黄色的乐队。我不太清楚如何实现的是背景条纹和时间标签。

我开始使用的一个选项是创建自定义UIView子类并将其设置为backgroundView的{​​{1}}属性。执行collectionView绘制垂直条纹很容易。

更难的部分是让时间标签始终显示在当前滚动区域的顶部/底部,而不是显示在backgroundView的边缘。有没有办法弄清楚我的背景视图的当前可见区域是什么,而不是drawRect:哪个是“完整”视图?

或者我应该以某种方式使用frame/boundsUICollectionView装饰功能。似乎不适合我在那里看到的API,但这是我的第一个UICollectionViewLayout,所以也许我错了?

更新

自从原帖以来,我已经学到了两件事,这让我比以前更加困惑:

  1. 当Apple的文档说:
  2.   

    此属性中的视图(如果有)位于所有的视图下方   其他内容和大小自动填充整个范围   集合视图。

    它们基本上是指设备的屏幕,而不是视图的实际范围。我发现在日志记录中,无论滚动,UICollectionViewbounds\frame参数始终都是屏幕的大小。

    1. 然后我想也许我可以使用drawRect:参数。我的想法是,我会使layoutAttributesForElementsInRect:符合传入的论点。不幸的是,这个矩形似乎经常比可视区域大。我假设他们在可见区域的边缘之外做了一些缓存。

2 个答案:

答案 0 :(得分:2)

这就是我最终做的事情。我实际上使用装饰视图结束了(ab?)。这就是我做的方式,我对结果非常满意:

我添加了一个TimeBarsView类,作为UICollectionReusableView的子类:

@interface TimeBarsView : UICollectionReusableView
@property (assign, nonatomic) NSInteger offset; // horizontal scroll offset
@end

我使用offset属性绘制背景视图,就好像它在drawRect:方法中滚动到该位置一样。把它粘在一起的那块是:

- (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
    [super applyLayoutAttributes: layoutAttributes];
    self.offset = layoutAttributes.indexPath.item;
}

这里的诀窍是我使用背景路径的IndexPath来传达其滚动位置。

在我的UIControllerViewLayout子类中,我实现了以下方法:

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

来自initWithCoderinit

- (void)registerTimeBars {
    [self registerClass:[TimeBarsView class] forDecorationViewOfKind:@"TimeBars"];
}

通常的layoutAttributesForElementsInRect:方法,前言如下:

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
    NSMutableArray *inRect = [NSMutableArray array];
    [inRect addObject:
        [self
            layoutAttributesForDecorationViewOfKind:@"TimeBars" // link to the TimeBars
            atIndexPath: [NSIndexPath
                indexPathForItem:self.collectionView.contentOffset.x // use the current scroll x value as the indexPath
                inSection:0]]];
    ... // other layouts for the normal item views like usual
    return inRect;
}

最后

- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind atIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:decorationViewKind withIndexPath:indexPath];
    CGPoint offset = self.collectionView.contentOffset;
    CGSize size = self.collectionView.bounds.size;
    // align current frame so it matches the current scroll box
    layoutAttributes.frame = CGRectMake(offset.x, offset.y, size.width, size.height);
    layoutAttributes.zIndex = -1; // make sure it's below other views
    return layoutAttributes;
}

答案 1 :(得分:1)

  

我应该以某种方式使用装饰功能......?

不,这些相当于UITableView中的页眉/页脚。他们不会在后台工作。

老实说,我觉得你过于复杂了。我只想制作两个UICollectionViews - 一个用于黄色/橙色/粉色条形图,另一个用于时间条形图。禁用底部集合视图上的用户交互。在scrollViewDidScroll:委托回调中,设置底部集合视图的内容偏移量以匹配顶部集合视图的内容偏移量。然后底部的一个将与顶部的一个滚动,它们将看起来像一个一样。