Автоматическая бесконечная коллекцияView - мигание

Я проверил несколько решений проблемы бесконечной прокрутки в UICollectionView, но ни один из них не работает отлично (1, 2, 3 и даже учебник - 4). Основная проблема заключается в том, что UICollectionView содержит изображения. Когда я просматриваю первый или последний элемент (чтобы сделать его бесконечным), перед загрузкой я вижу очень короткое "мигание", которое нужно удалить. Я не знаю, как это исправить, любая помощь будет любезно приветствована.

Я должен упомянуть, что галерея, которую я делаю, не должна допускать никакого взаимодействия с пользователем, она должна прокручиваться сама по себе (можно сказать, презентация).

Два самых интересных подхода, которые я пробовал:

Метод 1:14 элементов в коллекцииView, в таком порядке: @[8, 9, @[0-9], 0, 1] (так дублируются 8,9,1,2)

// a timer to move everything
_timer = [NSTimer scheduledTimerWithTimeInterval:0.02f target:self selector:@selector(scroll) userInfo:nil repeats:YES];
// timer selector
- (void)scroll {
 self.collectionView.contentOffset = CGPointMake(self.collectionView.contentOffset.x+1, self.collectionView.contentOffset.y);
}

// check if we need to change offset
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
 UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"something" forIndexPath:indexPath];
 if ([self scrollProperly]) {
 // return cell;
 }
}

// method to check & set proper offset (author: D33pN16h7)
- (BOOL)scrollProperly {
 // check if near the end or beginning
 BOOL test = NO;
 CGFloat currentOffsetX = self.collectionView.contentOffset.x;
 CGFloat currentOffSetY = self.collectionView.contentOffset.y;
 CGFloat contentWidth = self.collectionView.contentSize.width;

 if (currentOffsetX < (contentWidth / 6.0f)) {
 self.collectionView.contentOffset = CGPointMake((currentOffsetX + (contentWidth/2)), currentOffSetY);
 test = YES;
 }
 if (currentOffsetX > ((contentWidth * 4)/ 6.0f)) {
 self.collectionView.contentOffset = CGPointMake((currentOffsetX - (contentWidth/2)), currentOffSetY);
 test = YES;
 }
 return test;
}

Второй подход: 20 элементов в коллекцииView, в таком порядке: @[@[0-9], @[0-9]] (так что весь массив дублируется). Существует также таймер, аналогичный предыдущему методу. Вместо запуска [self scrollProperly] в collectionView:cellForItemAtIndexPath: здесь мы используем:

if (indexPath.row == 2) {
 [collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:([collectionView numberOfItemsInSection:indexPath.section] - 3) inSection:indexPath.section] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
} else if (indexPath.row == ([collectionView numberOfItemsInSection:indexPath.section] - 1)) {
 [collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:indexPath.section] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
}
2 ответа

Хорошо, мое окончательное решение состояло в том, чтобы сделать свиток очень длинным - в collectionView:cellForItemAtIndexPath: я читаю из своей базы данных по размеру. В collectionView:numberOfItemsInSection: существует постоянный размер. Когда я достигаю постоянного размера, я просматриваю первую строку. Поскольку я сделал постоянный размер, большое количество вспышек не раздражает пользователя, а свиток на самом деле бесконечен. Решение не идеально, но у меня нет другой идеи, как это исправить.


Я знаю, что это немного поздно, но я понял, как реализовать бесконечно прокручиваемое UICollectionView;

В зависимости от того, как выкладываются ваши ячейки, эта часть может отличаться, но по существу она разбивается на эти шаги.

1) Измените свой источник данных и дублируйте столько ячеек, сколько вам нужно на передней и задней части массива данных.

Например, если ваш массив данных выглядит следующим образом:

NSArray* array = @[@1, @2, @3, @4, @5];

и пусть говорят, что каждый из них занимает 1/5 от высоты представления, вы бы хотели изменить свой массив, чтобы выглядеть так:

NSArray* array = @[@4, @5, @1, @2, @3, @4, @5, @1, @2, @3];

Таким образом, ваш сборник по существу "повторяет" эти ячейки, чтобы создать иллюзию, что он продолжает двигаться.

Эта часть сложнее, потому что, как вы изменяете свой массив данных, зависит от того, сколько ячеек поместилось на экране сразу. Если только одна ячейка помещается на экране в то время, и ваш массив данных был @[@1, @2, @3], что может быть легко модифицирован для @[@3, @1, @2, @3, @1]; (Это пример из этого удивительного учебника.

Так почему мы это делаем? Это потому, что для коллекции требуется что-то для прокрутки, т.е. Дополнительное заполнение на передней и задней части коллекционного представления.

2) Использование значения ключевого значения для наблюдения за содержимымОфисный элемент коллекцииView.

[self.collectionView addObserver:self forKeyPath:@"contentOffset" options:0 context:NULL];

3) Проверьте, попало ли contentOffset к краю.

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
 CGFloat offset = self.collectionView.contentOffset.y;
 if(offset <= 1){
 [self.collectionView setContentOffset:CGPointMake(0, self.collectionView.height-2)];
 [self.collectionView reloadData];
}else if(offset >= self.collectionView.height-1){
 [self.collectionView setContentOffset:CGPointMake(0, 2)];
 [self.collectionView reloadData]; //call to reload the now visible cells, ensure delegate gets called
 }
}

Если contentOffset находится в пределах нескольких пикселей от верхнего края, тогда установите contentOffset так, чтобы представление коллекции молча прокручивало страницу без знания пользователем. Сделайте то же самое, когда contentOffset достигнет другого края.

Две ОЧЕНЬ ВАЖНЫЕ вещи.

1) Когда вы сначала инициализируете свой CollectionView, установите для contentOffset что-то вроде (0, 3). Таким образом, WONT запускает оператор if внутри метода KVO. 2) При настройке contentOffset в методе KVO также убедитесь, что заданная вами точка не будет вызывать оператор if при вызове метода.

Помните, что, поскольку вы наблюдаете за contentOffset, настройка contentOffset немедленно вызовет этот метод! Пока он не устанавливает contentOffset во второй раз, тем самым вызывая бесконечный цикл уведомлений об изменениях, вы должны быть в порядке.

Также не забудьте установить для collectionView.bounces значение YES.

licensed under cc by-sa 3.0 with attribution.