gpt4 book ai didi

ios - 如何绘制 UIView 的一部分,因为它在 UICollectionView 中变得可见?

转载 作者:可可西里 更新时间:2023-11-01 04:44:58 26 4
gpt4 key购买 nike

在 Android 上,我在水平滚动列表上有可能具有较大宽度的项目 View 。当 View 的一部分在列表中可见时, View 加载并绘制 block “图像”。这是一种优化,可避免一次绘制所有图像,因为这会造成浪费和缓慢。绘制的内容本质上是一个音频波形。 按照事情需要的方式去做 我不能将 block 拆分为列表中的单个 View 项。由于 android 绘图架构的工作方式,此策略非常有效。

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

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


解决方案 1:
检查 UIView 的哪些部分可见,并仅绘制那些可见的 block 。此解决方案的问题在于,随着 UICollectionView 滚动,UIView 不会绘制下一个变得可见的卡盘。以下是我所说内容的示例。

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

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


解决方案 2:
使用由 CATiledLayer 支持的自定义 UIView。这非常有效,因为它在滚动 UICollectionView 时绘制可见的图 block 。

问题在于,如果定义了 shouldDrawOnMainThread,则绘图发生在后台线程或下一个绘图周期。当 UIView 调整大小时或我的内部缩放逻辑启动时,这会带来问题。事情发生了变化,因为绘图周期与 View 大小调整不同步。


那么我如何才能像 CATiledLayer 那样收到通知,知道某个部分正在变得可见,并且我可以像 CALayer 支持的 UIView 一样正常绘制?


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

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

更新 2
经过多次测试和玩耍。使用解决方案 1 不是一种选择。当 UIView 达到一个巨大的宽度时,内存使用量会急剧下降,而使用 CATiledLayer 时,内存使用量将达到最低限度,正如我猜想的那样。 :/

最佳答案

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

您也可以尝试实现 shouldDrawOnMainThread 类方法,但这是一个私有(private)方法,您将面临被 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;
}
}

如果您想改为实现自己的平铺 层,您应该放弃平铺并尝试计算 View 的可见部分(部分和缩放级别)。比起你可以只绘制这部分作为图层的全部内容。

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

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

或者在 Swift 中

let theVisibleRect = frame.intersection(superlayer.bounds)

确定图层的可见区域。

关于ios - 如何绘制 UIView 的一部分,因为它在 UICollectionView 中变得可见?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48707815/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com