Загрузка дополнительных ячеек в нижней части UICollectionView
Я пытаюсь автоматически получить и загрузить следующую страницу ячеек, когда пользователь прокручивается в нижней части UICollectionView
.
Я могу сделать это, добавив нижний колонтитул UIButton
в UICollectoinView
. Когда пользователь прокручивается до нижнего колонтитула и касается кнопки, новые ячейки добавляются правильно. UIButton
в нижнем колонтитуле можно снова коснуться для добавления дополнительных страниц.
Я попытался автоматизировать его, поэтому, когда пользователь прокручивается донизу, правильный метод добавления новых ячеек вызывается автоматически:
- (UICollectionReuseableView *)collectionView: (UICollectionView *)collectionView viewForSupplementaryElementOfKind: (NSString *)kind atIndexPath: (NSIndexPath *) indexPath
{
// code for headerView
// ...
// code for footerView
MySupplementalFooter *footerView = nil;
if ( [kind isEqual:UICollectionElementKindSectionFooter] )
{
footerView = [self.collectionView dequeueReuseableSupplemntaryViewOfKind:kind withReuseIdentifier:@"FooterId" forIndexPath:indexPath];
if (LoadMoreIsEnabled)
{
footerView.loadMoreFooterButton.setHidden:NO];
[self loadMoreFooterButtonAction]; // calls the method to add cells to the dictionary for cv
} else
{
footerView.loadMoreFooterButton setHidden:YES];
}
return footerView;
}
}
Вызывается метод loadMoreFooterButtonAction
, но весь пробег UICollectionView
завершается. Обновление UICollectionView
не возвращает его.
Ответы
Ответ 1
Я предполагаю, что вы пытаетесь сделать что-то вроде "бесконечной прокрутки" на веб-страницах рабочего стола, где вы загружаете больше контента, когда пользователь попадает в нижнюю часть страницы. В iOS это не очень часто используемый дизайн. Как правило, разработчики будут инициализировать UITableView или UICollectionView с абсолютным общим количеством записей. Если им необходимо передавать данные по сети, они асинхронно загружают данные по мере необходимости (когда ячейки или представления появляются на экране), и пока контент не загружается, они не показывают какой-то временный контент, как пустой вид с помощью счетчика.
Тем не менее, если вы хотите делать бесконечную прокрутку в стиле, похожем на настольное веб-приложение, вы должны реализовать протокол UIScrollViewDelegate (или UICollectionViewDelegate, который является надмножеством) и прослушать scrollViewDidScroll: обратный вызов. В рамках этого обратного вызова выполните итерацию через UICollectionView indexPathsForVisibleItems и проверьте, не указана ли какой-либо из путей указателя к "последнему" элементу в вашей коллекции, который указывает, что пользователь прокручивается до конца. В этот момент позвоните в свою логику, чтобы загрузить больше материала.
Ответ 2
В IOS8 существует метод UICollectionViewDelegate
willDisplayCell
.
func collectionView(collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) {
if indexPath.item == (data.count-1) {
loadData()
}
}
Ответ 3
В представлении таблицы вы должны загрузить больше данных в метод willDisplayCell(). В коллекциях нет такого аналога. Но вы можете так поступить. Надеюсь, это помогает.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
// Other code here ...
if (indexPath.item == [self.photos count] - 1) {
[self loadPhotos];
}
return cell;
}
- (void)loadPhotos {
[self showLoadingIndicator];
self.operation = [client HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
[self hideLoadingIndicator];
// Get data
NSArray *photosData = responseObject[@"data"];
NSInteger numberOfResults = [photosData count];
NSInteger totalCount = [self.photos count];
if (numberOfResults > 0) {
NSMutableArray *indexPaths = [NSMutableArray new];
for (NSInteger i = 0; i < numberOfResults; i++) {
Photo *photo = [Photo new];
photo._id = [photoData[@"id"] integerValue];
photo.url = photoData[@"url"];
[self.photos addObject:photo];
[indexPaths addObject:[NSIndexPath indexPathForRow:totalCount + i
inSection:0]];
}
[self.collectionView performBatchUpdates:^{
[self.collectionView insertItemsAtIndexPaths:indexPaths];
} completion:nil];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[self hideLoadingIndicator];
// Handle error here
}];
[self.operation start];
}
Ответ 4
Я знаю, что это старый вопрос, но я предоставлю решение для будущих ищущих ответ. Обычно, когда я делаю бесконечную прокрутку на UITableView, я проверю, пересекаются ли границы прокрутки viewView TableView с прямоугольником tableFooterView. Представления нижнего колонтитула немного сложнее получить в UICollectionViews, поэтому я создаю прямоугольник в конце коллекцииView, чтобы увидеть, пересекается ли он с границами scrollView, и если это произойдет, я загружаю больше элементов. Я также проверил, что у нас есть хотя бы что-то в таблице, поэтому я не буду одинок, пытаясь загрузить больше прав, когда эта таблица создает экземпляр.
Примечание. Ваш метод more
в этом случае обновит ваш источник данных collectionView, добавив новые элементы. Методы numberOfItems/sections должны отражать новые подсчеты.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (CGRectIntersectsRect(scrollView.bounds, CGRectMake(0, self.collectionView.contentSize.height, CGRectGetWidth(self.view.frame), 40)) && self.collectionView.contentSize.height > 0)
{
[self more];
}
}
Ответ 5
Мне не удалось преобразовать ответ @sukhrob в swift для моего проекта, поэтому вот его код в Swift 3 для удобства копирования и вставки.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// Other code here ...
if indexPath.item == photos.count() - 1 {
loadPhotos()
}
return cell
}
func loadPhotos() {
showLoadingIndicator()
operation = client.httpRequestOperation(with: request, success: {(_ operation: AFHTTPRequestOperation, _ responseObject: Any) -> Void in
self.hideLoadingIndicator()
// Get data
let photosData: [Any] = responseObject["data"]
let numberOfResults: Int = photosData.count
let totalCount: Int = photos.count()
if numberOfResults > 0 {
var indexPaths = [Any]()
var i = 0
while i < numberOfResults {
let photo = Photo()
photo.id = CInt(photoData["id"])
photo.url = photoData["url"]
photos.append(photo)
indexPaths.append(IndexPath(row: totalCount + i, section: 0))
i
}
i += 1
collectionView?.performBatchUpdates({() -> Void in
collectionView?.insertItems(at: indexPaths as? [IndexPath] ?? [IndexPath]())
}) { _ in }
}
}, failure: {(_ operation: AFHTTPRequestOperation, _ error: Error?) -> Void in
self.hideLoadingIndicator()
// Handle error here
})
operation.start()
Ответ 6
Вы также можете использовать collectionView(_:prefetchItemsAt:)
Учебное пособие 1 и 2.