【发布时间】:2018-07-20 08:11:04
【问题描述】:
在 Android 上,我在水平滚动列表上有可能具有较大宽度的项目视图。当视图的一部分在列表中可见时,视图会加载并绘制块“图像”。这是避免一次绘制所有图像的优化,因为它会浪费且缓慢。绘制的内容本质上是一个音频波形。 按需要工作的方式做事 我不能将块拆分为列表中的单个视图项。 由于 android 绘图架构的工作原理,此策略非常有效。
现在我正在尝试在 iOS 中使用类似的模式,但遇到了一些麻烦,我不太确定如何提出解决方案。
在 iOS 中,我使用 UICollectionView 绘制大宽度单元格,我们需要同样优化加载和仅绘制可见块。
解决方案 1:
检查UIView 的哪些部分是可见的并只绘制那些可见的块。此解决方案的问题在于,当UICollectionView 滚动时,UIView 不会绘制下一个可见的卡盘。以下是我所说的示例。
UIView 加载初始块
这些可以通过它们不同的块颜色看到:
滚动一下
显示黑色并且没有加载任何内容,因为没有提示需要再次绘制视图,因此我们无法加载下一个可见块。
解决方案 2:
使用由CATiledLayer 支持的自定义UIView。这很完美,因为它会在滚动UICollectionView 时绘制瓷砖,因为它们变得可见。
问题是如果定义了shouldDrawOnMainThread,则绘制发生在后台线程或下一个绘制周期。当UIView 调整大小或我的内部缩放逻辑启动时,这会带来问题。事情发生了变化,因为绘图周期与调整视图大小不同步。
那么我怎么能像CATiledLayer 这样得到通知,告诉我某个部分变得可见并且我可以像CALayer 支持UIView 一样正常绘制呢?
更新 1
我正在研究使用preferredLayoutAttributesFittingAttributes 作为检查是否需要绘制新块的方法。每次单元格由于滚动而移动到新位置时都会调用此方法。希望这不是一个坏主意。 :)
- (UICollectionViewLayoutAttributes *)preferredLayoutAttributesFittingAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes
更新 2
经过多次测试和玩耍。使用解决方案 1 不是一种选择。当UIView 达到一个巨大的宽度时,内存使用量会飙升,而使用CATiledLayer 的内存使用量是最小的,正如我猜想的那样。 :/
【问题讨论】:
-
你真的试过
func draw(_ rect: CGRect)吗? -
@MichaelVorontsov 好吧,这并不是真正的问题。 :P 绘图没问题。问题是仅触发可见区域的绘图。在我的更新 #2 中,我遇到了一个限制,使 CATiledLayer 或多或少地成为了答案。 ://
-
func setNeedsDisplay(CGRect)?仅当您要求绘制特定矩形时,您可以提供额外的标志来进行绘制,并且在标志下降时不绘制任何内容。
标签: ios uiview uicollectionview calayer catiledlayer