How to draw parts of a UIView as it becomes visible inside UICollectionView?

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-10 14:44:59

问题


On Android I have item views with potentially large widths on a horizontal scrolling list. The view loads and draws chunks "images" as parts of the view become visible on the list. This is an optimization to avoid drawing all images at once as it would be wasteful and slow. The content drawn is essentially an audio waveform. Do to the ways things need to work I can't split the chunks as individual view items on a list. This strategy works perfect because of how android drawing architecture works.

Now I'm trying to use a similar pattern in iOS but I'm having some trouble and I'm not too sure how to come up with a solution.

In iOS I'm are using a UICollectionView which draws large width Cells and we need that same optimization of loading and drawing only the visible chunks.


Solution 1:
Check what parts of the UIView is visible and draw only those visible chunks. The problem with this solution is that as the UICollectionView scrolls the UIView doesn't draw the next chucks that are becoming visible. Here are examples of what I'm talking about.

UIView loads initial chunks
These can be seen by their different chunk colors:

Scroll a bit
Black is shown and no content is loaded because there is no hint that the view needs to draw again so we can't load the next visible chunk.


Solution 2:
Use custom UIView backed by a CATiledLayer. This works perfect because it draws the tiles as they become visible while scrolling the UICollectionView.

The problem is that drawing happens on the background thread or on the next drawing cycle if shouldDrawOnMainThread is defined. This brings issues when the UIView is resized or my internal zoom logic kicks. Things shift because the drawing cycle is not synchronized to the view resizing.


So how could I get notified like CATiledLayer that a part is becoming visible and I could draw normally like a CALayer backed UIView?


UPDATE 1
I'm looking into using preferredLayoutAttributesFittingAttributes as a way to check if a new chunk need to be drawn. This is called every time the cell is moved into a new position because of scrolling. Hopefully, this isn't a bad idea. :)

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

UPDATE 2
After much testing and playing around. Using solution 1 is not an option. When a UIView reaches a huge width memory usage goes off the roof while using CATiledLayer memory usage is at minimal as I guess one would expect. :/


回答1:


I don't know if you can completely turn off the effect. You can soften it by setting the fadeDuration to 0. To do this, you must create a subclass of CATiledLayer and overwrite the class method fadeDuration.

You can also try to implement shouldDrawOnMainThread class method, but this is a private method, and you're risking a rejection on the App Store:

@implementation MyTiledLayer

+(CFTimeInterval)fadeDuration {
    return 0.0;
}

+ (BOOL)shouldDrawOnMainThread {
    return YES;
}

@end

or in Swift:

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

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

If you want to implement your own tiled layer instead, you should waive of the tiles and try to compute the visible part (section and zoom level) of the view. Than you can draw only this part as layer whole content.

Apparently, there is no easy way to re-draw the view when the scrollview is scrolling. But you may implement scrollViewDidScroll:, and trigger the redrawing manually. The visibleRect method always returns the complete area of the layer, but you can use

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

or in Swift

let theVisibleRect = frame.intersection(superlayer.bounds)

to determine the visible area of the layer.



来源:https://stackoverflow.com/questions/48707815/how-to-draw-parts-of-a-uiview-as-it-becomes-visible-inside-uicollectionview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!