【问题标题】:How to get scroll savvy background for UICollectionView如何获得 UICollectionView 的滚动精通背景
【发布时间】:2014-02-25 19:24:19
【问题描述】:

使用UICollectionViewController 和我自己的UICollectionViewLayout 子类,我整理了一个显示甘特样式时间表的视图。使用那个框架来做乐队真的很容易。

对我来说不清楚的是如何设计提供时间上下文的支持视图。我在 Inkscape 中画了一个例子:

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

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

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

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

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

更新

自最初的帖子以来,我学到了 2 件事,这让我比以前更加困惑如何做到这一点:

  1. 当 Apple 的文档说:

此属性中的视图(如果有)位于所有 其他内容并自动调整大小以填充整个边界 集合视图。

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

  1. 然后我想也许我可以使用layoutAttributesForElementsInRect: 参数。我的想法是让UICollectionViewLayoutAttributes 适合传入的参数。不幸的是,这个矩形似乎经常大于可视区域。我认为它们会在可见区域的边缘之外进行一些缓存。

【问题讨论】:

    标签: ios ios7 uicollectionview


    【解决方案1】:

    这就是我最终要做的。我实际上最终(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;
    }
    

    【讨论】:

    • 如果您的解决方案不是秘密的,您是否有机会(或可能已经)将其放在 Github 或其他地方?我正在尝试做类似的事情(一个表示各种活动持续时间的条形图),并且我正忙着让我的菜鸟绕开它,特别是自定义布局方面。周围的教程似乎很少。谢谢!
    【解决方案2】:

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

    不,这些相当于 UITableView 中的页眉/页脚。它们不适用于背景。

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

    【讨论】:

    • 好的,我做到了。我不确定我会称之为“复杂”(双关语?),但它确实有效。以下任何一个想法会更简单吗? 1) 而不是 UICollectionView 用于背景视图,只需执行普通的 UIView 子类并使用 CoreGraphics 调用绘制条纹/文本。做酒吧还不错。必须重叠的文本才开始变得很多。 2) 自己创建UICollectionView的子类,覆盖drawRect:绘制背景,然后调用super?
    • 我的猜测是那些性能会降低。我个人认为它们更复杂。但同时实现两者并使用 Time Profiler 来查看哪个性能更高也无妨。
    • 我的图表并不大。所以我并不太强调强调性能。对代码的简单性更感兴趣。
    • 您可以将 UICollectionView 的 backgroundColor 设置为由 [UIColor -colorWithPatternImage:] 制成的颜色,而不是 #2。您可能仍需要为文本标签覆盖 drawRect:
    猜你喜欢
    • 1970-01-01
    • 2019-10-19
    • 2019-05-19
    • 1970-01-01
    • 1970-01-01
    • 2013-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多