在Android上,我在水平滚动列表中有可能有大宽度的项目视图。视图加载并绘制块"图像"视图的一部分在列表中可见。这是一种优化,以避免一次性绘制所有图像,因为它会浪费和缓慢。绘制的内容基本上是音频波形。 确定需要工作的方式我不能将这些块拆分为列表中的单个视图项。由于android绘图架构的工作原理,这种策略非常有效。
现在我尝试在iOS中使用类似的模式,但我遇到了一些问题,而且我不太确定如何提出解决方案。
在iOS中,我正在使用UICollectionView
绘制大宽度单元格,我们需要同样优化加载和仅绘制可见块。
解决方案1:
检查UIView
的哪些部分是可见的,并仅绘制那些可见的块。此解决方案的问题在于,当UICollectionView
滚动UIView
时,不会绘制下一个可见的卡盘。以下是我所谈论的例子。
滚动
显示黑色并且未加载任何内容,因为没有提示视图需要再次绘制,因此我们无法加载下一个可见块。
解决方案2:
使用由UIView
支持的自定义CATiledLayer
。这非常有效,因为它会在滚动UICollectionView
时显示图块,因为它们变得可见。
问题是如果定义了shouldDrawOnMainThread
,则在后台线程或下一个绘图周期中进行绘制。这会在UIView
调整大小或内部缩放逻辑启动时出现问题。事情发生了变化,因为绘图周期没有与视图大小调整同步。
那么我怎样才能收到像CATiledLayer
这样的通知,告知某个部件变得可见,我可以像CALayer
支持的UIView
一样正常绘制?
更新1
我正在研究如何使用preferredLayoutAttributesFittingAttributes
来检查是否需要绘制新的块。每次由于滚动而将单元格移动到新位置时都会调用此方法。希望这不是一个坏主意。 :)
- (UICollectionViewLayoutAttributes *)preferredLayoutAttributesFittingAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes
更新2
经过多次测试和玩耍。使用解决方案1不是一种选择。当UIView
到达一个巨大的宽度内存时,使用CATiledLayer
内存的使用率会下降到最低限度,因为我猜是人们会想到的。 :/
答案 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)
确定图层的可见区域。