Ios 如何获取UICollectionView的scroll-Savy背景

Ios 如何获取UICollectionView的scroll-Savy背景,ios,ios7,uicollectionview,Ios,Ios7,Uicollectionview,使用UICollectionViewController和我自己的UICollectionViewLayout子类,我创建了一个显示Gannt样式时间图表的视图。使用这个框架来制作乐队真的很容易 我不太清楚的是如何设计提供时间上下文的支持视图。我在Inkscape中草拟了一个示例: 黑色矩形轮廓是用户当前可能滚动到的位置的示例 所以,我知道如何做粉红色/橙色/黄色的乐队。我不太清楚如何实现的是背景条带和时间标签 我开始使用的一个选项是创建一个自定义的UIView子类,并将其设置为我的colle

使用
UICollectionViewController
和我自己的
UICollectionViewLayout
子类,我创建了一个显示Gannt样式时间图表的视图。使用这个框架来制作乐队真的很容易

我不太清楚的是如何设计提供时间上下文的支持视图。我在Inkscape中草拟了一个示例:

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

所以,我知道如何做粉红色/橙色/黄色的乐队。我不太清楚如何实现的是背景条带和时间标签

我开始使用的一个选项是创建一个自定义的
UIView
子类,并将其设置为我的
collectionView
backgroundView
属性。使用
drawRect:
绘制垂直条纹会很容易

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

或者我应该以某种方式使用
UICollectionView
UICollectionView布局的装饰功能。看起来不太适合我在那里看到的API,但这是我的第一个
UICollectionView
,所以也许我错了

更新

从最初的帖子开始,我学到了两件事,这让我比以前更加困惑如何做到这一点:

  • 当苹果的文档说:
  • 此属性中的视图(如果有)位于所有 其他内容,并自动调整大小以填充 集合视图

    它们基本上是指设备的屏幕,而不是视图的实际范围。通过日志记录,我发现无论滚动如何,
    bounds\frame
    drawRect:
    参数始终是屏幕的大小

  • 然后我想也许我可以使用
    layouttributesforementsinrect:
    参数。我的想法是将
    UICollectionViewLayoutAttribute
    与传入参数相匹配。不幸的是,这个矩形似乎经常大于可视区域。我假设它们在可见区域的边缘之外进行缓存
  • 我是否应该以某种方式使用装饰功能

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

    老实说,我认为你把它复杂化了。我只需要创建两个UICollectionView——一个用于黄色/橙色/粉色条,另一个用于时间条。在底部集合视图上禁用用户交互。在
    scrollViewDidScroll:
    delegate回调中,设置底部集合视图的内容偏移量以匹配顶部集合视图的内容偏移量。然后底部的一个将与顶部的一个滚动,它们将显示为一个整体工作

    我是否应该以某种方式使用装饰功能

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

    老实说,我认为你把它复杂化了。我只需要创建两个UICollectionView——一个用于黄色/橙色/粉色条,另一个用于时间条。在底部集合视图上禁用用户交互。在
    scrollViewDidScroll:
    delegate回调中,设置底部集合视图的内容偏移量以匹配顶部集合视图的内容偏移量。然后底部的一个将与顶部的一个滚动,它们将显示为一个整体工作

    我是否应该以某种方式使用装饰功能

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

    老实说,我认为你把它复杂化了。我只需要创建两个UICollectionView——一个用于黄色/橙色/粉色条,另一个用于时间条。在底部集合视图上禁用用户交互。在
    scrollViewDidScroll:
    delegate回调中,设置底部集合视图的内容偏移量以匹配顶部集合视图的内容偏移量。然后底部的一个将与顶部的一个滚动,它们将显示为一个整体工作

    我是否应该以某种方式使用装饰功能

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


    老实说,我认为你把它复杂化了。我只需要创建两个UICollectionView——一个用于黄色/橙色/粉色条,另一个用于时间条。在底部集合视图上禁用用户交互。在
    scrollViewDidScroll:
    delegate回调中,设置底部集合视图的内容偏移量以匹配顶部集合视图的内容偏移量。然后,底部的一个将与顶部的一个滚动,它们将显示为一个整体工作。

    下面是我最后要做的。实际上,我最终(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;
    }
    
    这里的技巧是,我使用背景路径的
    indepath
    来传递其滚动位置

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

    - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
        return YES;
    }
    
    initWithCoder
    init
    调用:

    - (void)registerTimeBars {
        [self registerClass:[TimeBarsView class] forDecorationViewOfKind:@"TimeBars"];
    }
    
    通常的
    layouttributesforementsinrect:
    方法的前导码如下:

    - (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;
    }
    

    这就是我最后做的。我表演