У меня есть месяц, похожий на календарь iOS, и используется UICollectionView
. Теперь было бы интересно реализовать бесконечное поведение прокрутки, чтобы пользователь мог прокручивать в каждом направлении по вертикали, и он никогда не кончится. Вопрос в том, как можно эффективно реализовать такое поведение? Вот что я узнал сейчас:
В основном вы можете проверить, попали ли вы в конец текущего вида прокрутки. Вы можете проверить это в scrollViewDidScroll:
или в collectionView:cellForItemAtIndexPath:
. Было бы просто добавить еще один контент в источник данных, но я думаю, что есть нечто большее. Если вы только добавляете данные, вы можете прокручивать их вниз, например. Пользователь должен иметь возможность прокручивать в обоих направлениях (вверх, вниз). Не знаю, выполнит ли это reloadData
трюк. Также изменится contentOffset
, и не должно быть никаких прыгающих действий.
Другой возможностью было бы использовать подход Advanced ScrollView Techniques WWDC 2011. Здесь layoutSubviews
используется, чтобы установить contentOffset
в центр UIScrollView
, и кадры подсмотров настроены на ту же величину расстояния от центра. Этот подход будет работать нормально, если у меня нет разделов. Как это будет работать с разделами?
Я не хочу использовать большое значение для количества секций для подделки бесконечного прокрутки, потому что пользователь найдет конец. Также я не использую пейджинг.
Итак, как я могу реализовать бесконечную прокрутку для представления коллекции?
Edit:
Теперь я попытался увеличить число секций, если попал в конец UICollectionView
. Чтобы показать новые разделы, нужно вызвать reloadData
. При вызове этого метода все вычисления для всех текущих доступных разделов выполняются снова! Эта проблема с производительностью вызывает большие заикания при прокрутке списка коллекций, и при прокрутке вниз она становится медленнее и медленнее. Не знаю, можно ли перенести эту работу на фоновый поток. При таком подходе можно прокручивать вверх и вниз, если вы сделаете необходимые адаптации.
Bounty:
Теперь я предлагаю щедрость за ответ на этот вопрос. Меня интересует, как реализуется представление месяца в календаре iOS. Подробнее о том, как работает бесконечная прокрутка. Здесь он работает в обоих направлениях (вверх, вниз), и он никогда не заканчивается (реальный бесконечный - не повторяющийся). Также нет никакого отставания (даже на iPhone 4). Я хочу использовать UICollectionView
, и данные состоят из разных разделов, и каждый раздел имеет различное количество элементов. Нужно сделать некоторые вычисления, чтобы получить следующий раздел. Мне не нужна календарная часть - только бесконечное поведение прокрутки с различными элементами в разделе. Не стесняйтесь задавать вопрос.
Добавление разделов:
public override void Scrolled(UIScrollView scrollView)
{
NSIndexPath[] currentIndexPaths = currentVisibleIndexPaths();
// if we are at the top
if (currentIndexPaths.First().Section == 0)
{
NSIndexPath oldIndexPath = NSIndexPath.FromItemSection(0, 0);
UICollectionViewLayoutAttributes attributes_before = this.controller.CollectionView.GetLayoutAttributesForItem(oldIndexPath);
CGRect before = attributes_before.Frame;
CGPoint contentOffset = this.controller.CollectionView.ContentOffset;
this.controller.CollectionView.PerformBatchUpdatesAsync(delegate ()
{
// some calendar calculations and updating the data source not shown here
this.controller.CurrentNumberOfSections += 12;
this.controller.CollectionView.InsertSections(NSIndexSet.FromNSRange(new NSRange(0, 12)));
}
);
NSIndexPath newIndexPath = NSIndexPath.FromItemSection(0, 12);
UICollectionViewLayoutAttributes attributes_after = this.controller.CollectionView.GetLayoutAttributesForItem(newIndexPath);
CGRect after = attributes_after.Frame;
contentOffset.Y += (after.Y - before.Y);
this.controller.CollectionView.SetContentOffset(contentOffset, false);
}
// if we are near the end
if (currentIndexPaths.Last().Section == this.controller.CurrentNumberOfSections - 1)
{
this.controller.CollectionView.PerformBatchUpdatesAsync(delegate ()
{
// some calendar calculations and updating the data source not shown here
this.controller.CollectionView.InsertSections(NSIndexSet.FromNSRange(new NSRange(this.controller.CurrentNumberOfSections, 12)));
this.controller.CurrentNumberOfSections += 12;
}
);
}
}
Если мы приближаемся к вершине, приложение падает с помощью
Снимок снимка, который не был отображен, приводит к пустой снимок. Убедитесь, что ваше представление было просмотрено не ранее, чем раньше моментальный снимок или моментальный снимок после обновлений экрана. Утверждение об отказе в - [Procet_UICollectionViewCell _addUpdateAnimation],/SourceCache/UIKit_Sim/UIKit-2935.137/UICollectionViewCell.m:147
Я думаю, что он сбой, потому что он называется слишком часто. Если я удалю адаптеры contentOffset, это сработает, но я всегда на высоте. Если я нахожусь на вершине, добавляются и другие разделы. Поэтому этот алгоритм должен быть ограничен. У меня также есть начальное смещение содержимого. Это смещение неверно, поскольку при инициализации алгоритм также вызывается и добавляет некоторые разделы. Теперь я попытался добавить разделы в didEndDisplayingCell
, но он сработает.
Добавление разделов в конец действительно работает, но это не имеет значения, когда я добавляю его (один раздел перед или 10 разделов раньше). Когда обновление происходит, прокрутка немного заикается. Еще одна вещь, которую я пробовал, - уменьшить количество секций с 12 до 3, но затем все больше и больше заикается.