Как нарисовать части UIView, как он становится видимым внутри UICollectionView?
На Android у меня есть представления элементов с потенциально большой шириной в горизонтальном списке прокрутки. Представление загружает и рисует фрагменты "изображения", когда части представления становятся видимыми в списке. Это оптимизация, позволяющая избежать рисования всех изображений одновременно, поскольку это будет расточительным и медленным. Нарисованный контент по сути является звуковой формой волны. Делать так, как нужно, чтобы все работало. Я не могу разделить фрагменты как отдельные элементы в списке. Эта стратегия прекрасно работает из-за того, как работает архитектура рисования Android.
Сейчас я пытаюсь использовать подобный шаблон в iOS, но у меня возникли некоторые проблемы, и я не слишком уверен, как найти решение.
В iOS я использую UICollectionView
который рисует ячейки большой ширины, и нам нужна та же оптимизация загрузки и рисование только видимых фрагментов.
Решение 1:
Проверьте, какие части UIView
виден и рисует только те видимые куски. Проблема с этим решением заключается в том, что в качестве UICollectionView
прокручивает UIView
не рисует следующие патроны, которые становятся видимыми. Вот примеры того, о чем я говорю.
UIView
загружает начальные куски
Их можно увидеть по разным цветам:
Прокрутите немного
Показывается черный цвет, и содержимое не загружается, потому что нет никаких намеков на то, что представление должно быть прорисовано снова, поэтому мы не можем загрузить следующий видимый фрагмент.
Решение 2:
Использовать пользовательские UIView
при поддержке CATiledLayer
, Это прекрасно работает, потому что рисует плитки, когда они становятся видимыми при прокрутке UICollectionView
,
Проблема в том, что рисование происходит в фоновом потоке или в следующем цикле рисования, если shouldDrawOnMainThread
определено. Это вызывает проблемы, когда UIView
изменен размер или моя внутренняя логика увеличения Все меняется, потому что цикл рисования не синхронизирован с изменением размера вида.
Так как я мог получить уведомление, как CATiledLayer
что часть становится видимой, и я мог бы рисовать нормально, как CALayer
со спинкой UIView
?
ОБНОВЛЕНИЕ 1
Я смотрю на использование preferredLayoutAttributesFittingAttributes
как способ проверить, нужно ли рисовать новый кусок. Это вызывается каждый раз, когда ячейка перемещается в новую позицию из-за прокрутки. Надеюсь, это неплохая идея.:)
- (UICollectionViewLayoutAttributes *)preferredLayoutAttributesFittingAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes
ОБНОВЛЕНИЕ 2
После долгих испытаний и тренировок. Использование решения 1 не вариант. Когда UIView
достигает огромной ширины памяти использование уходит с крыши при использовании CATiledLayer
использование памяти минимально, как я и ожидал.:/
1 ответ
Я не знаю, сможете ли вы полностью отключить эффект. Вы можете смягчить его, установив 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);
или в Свифте
let theVisibleRect = frame.intersection(superlayer.bounds)
определить видимую область слоя.