如何在UICollectionView中显示UIView的部分?

时间:2018-02-09 14:14:24

标签: ios uiview uicollectionview calayer catiledlayer

在Android上,我在水平滚动列表中有可能有大宽度的项目视图。视图加载并绘制块"图像"视图的一部分在列表中可见。这是一种优化,以避免一次性绘制所有图像,因为它会浪费和缓慢。绘制的内容基本上是音频波形。 确定需要工作的方式我不能将这些块拆分为列表中的单个视图项。由于android绘图架构的工作原理,这种策略非常有效。

现在我尝试在iOS中使用类似的模式,但我遇到了一些问题,而且我不太确定如何提出解决方案。

在iOS中,我正在使用UICollectionView绘制大宽度单元格,我们需要同样优化加载和仅绘制可见块。

解决方案1:
检查UIView的哪些部分是可见的,并仅绘制那些可见的块。此解决方案的问题在于,当UICollectionView滚动UIView时,不会绘制下一个可见的卡盘。以下是我所谈论的例子。

UIView加载初始块
这些可以通过它们的不同块颜色看出: enter image description here

滚动
显示黑色并且未加载任何内容,因为没有提示视图需要再次绘制,因此我们无法加载下一个可见块。 enter image description here

解决方案2:
使用由UIView支持的自定义CATiledLayer。这非常有效,因为它会在滚动UICollectionView时显示图块,因为它们变得可见。

问题是如果定义了shouldDrawOnMainThread,则在后台线程或下一个绘图周期中进行绘制。这会在UIView调整大小或内部缩放逻辑启动时出现问题。事情发生了变化,因为绘图周期没有与视图大小调整同步。

那么我怎样才能收到像CATiledLayer这样的通知,告知某个部件变得可见,我可以像CALayer支持的UIView一样正常绘制?

更新1
我正在研究如何使用preferredLayoutAttributesFittingAttributes来检查是否需要绘制新的块。每次由于滚动而将单元格移动到新位置时都会调用此方法。希望这不是一个坏主意。 :)

- (UICollectionViewLayoutAttributes *)preferredLayoutAttributesFittingAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes

更新2
经过多次测试和玩耍。使用解决方案1不是一种选择。当UIView到达一个巨大的宽度内存时,使用CATiledLayer内存的使用率会下降到最低限度,因为我猜是人们会想到的。 :/

1 个答案:

答案 0 :(得分:2)

我不知道你是否可以完全关闭效果。您可以通过将fadeDuration设置为0来软化它。为此,您必须创建CATiledLayer的子类并覆盖类方法fadeDuration

您也可以尝试实施shouldDrawOnMainThread类方法,但这是一种私有方法,您可能会在App Store上遭到拒绝:

@implementation MyTiledLayer

+(CFTimeInterval)fadeDuration {
    return 0.0;
}

+ (BOOL)shouldDrawOnMainThread {
    return YES;
}

@end

或在Swift中:

class MyTiledLayer: CATiledLayer {
    override class func fadeDuration() -> CFTimeInterval {
        return 0.0
    }

    class func shouldDrawOnMainThread() -> Bool {
        return true;
    }
}

如果您想要实现自己的平铺图层,则应放弃图块并尝试计算视图的可见部分(部分和缩放级别)。您只能将此部分绘制为图层整体内容。

显然,滚动滚动视图时没有简单的方法可以重新绘制视图。但您可以实现scrollViewDidScroll:,并手动触发重绘。 visibleRect方法始终返回图层的完整区域,但您可以使用

CGRect theVisibleRect = CGRectIntersection(self.frame, self.superlayer.bounds);

或在Swift中

let theVisibleRect = frame.intersection(superlayer.bounds)

确定图层的可见区域。