UICollectionView с FlowLayout не прокручивается при настройке вставок раздела

Я использую UICollectionView программно.

Я установил его рамку следующим образом:

UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 100, self.view.frame.size.width, 3000) collectionViewLayout:flowLayout];

У моего UICollectionViewFlowLayout есть вставка раздела, установленная как:

flowLayout.sectionInset = UIEdgeInsetsMake(20.0, 20.0, 100.0, 20.0);

У меня тоже только 1 часть.

Я установил высоту 3000, чтобы увидеть, будет ли прокручиваться представление коллекции, но это не так. Я устанавливаю это так, поскольку представление коллекции не прокручивается вверх или вниз, когда я вставляю новые элементы.

UICollectionView является подклассом UIScrollView, что означает, что я могу продолжать сбрасывать размер содержимого прокрутки. Будет ли это работать должным образом?

Единственная проблема заключается в том, что это сработает, если я знаю размеры всех элементов, включая количество элементов в каждой строке.

Если бы каждый элемент имел разный размер, как бы я узнал размер каждой строки? Мне нужно, чтобы добавить все размеры строк и увеличить высоту размера содержимого self.collectionView.

ИЗМЕНИТЬ

Даже мое предложение выше, сброс размера содержимого, не работает должным образом! Я пробовал следующее при обновлении представления моей коллекции:

 int numberOfRows = self.dataArray.count / 3;
self.collectionView.contentSize = CGSizeMake(self.view.frame.size.width, (numberOfRows * 200) + 300);

Хотя это очень некрасиво. Это связано с тем, что предполагается, что все мои изображения имеют размер 200x200 пикселей, что соответствует 3 изображениям в строке (отсюда и деление на 3).

Кроме того, даже с +300, которые у меня есть, последнюю строку я вижу только на 3/4, а не на всю. Мне нужно прокрутить больше, и я смогу это увидеть, но он снова возвращается к 3/4. Это похоже на прокрутку для обновления, когда представление перемещается только в том случае, если вы его перетаскиваете, а когда вы оставляете его, оно возвращается туда, где оно было. Почему это происходит? Просто Apple так плохо спроектировала UICollectionView? Это немного нелепо... UITableViews автоматически настраивают свою прокрутку в соответствии с их содержимым.


person darksky    schedule 01.10.2012    source источник


Ответы (3)


Отвечая на некоторые другие ваши вопросы о UICollectionView, я создал этот демонстрационный проект, и он отлично прокручивается, поэтому я не знаю, с чем вы столкнулись. Единственное, что мне нужно было сделать, чтобы сделать последнюю строку полностью видимой, — это увеличить размер нижней вставки до 90. Я также добавил метод завершения в PerformBatchUpdates:completion: для автоматической прокрутки, чтобы последний добавленный элемент был виден ( обратите внимание, что я добавляю некоторые дополнительные элементы с помощью PerformSelector;withObject:afterDelay:). Мои изображения имеют размер 48x48, и я просто установил представление коллекции в соответствии с представлением моего контроллера. Вот код, чтобы вы могли сравнить его с тем, что у вас есть:

@interface ViewController () <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout> {
NSMutableArray *newData;
}
 @property (nonatomic, retain) UICollectionView *collectionView;
 @property (nonatomic, retain) NSMutableArray *results;
 @end

@implementation ViewController

- (void)viewDidLoad {
    self.results = [NSMutableArray array];
    int i = 11;
    while (i<91) {
        UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"New_PICT00%d.jpg",i]];
        [self.results addObject:image];
        i++;
    }

    UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
    //flowLayout.scrollDirection =  UICollectionViewScrollDirectionHorizontal;

    self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:flowLayout];
    self.collectionView.dataSource = self;
    self.collectionView.delegate = self;
    self.view.backgroundColor = [UIColor blackColor];
    [self.view addSubview:self.collectionView];
    [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"Cell"];
    //[self.collectionView registerClass:[RDCell class] forCellWithReuseIdentifier:@"myCell"];
    [self.collectionView reloadData];

    [self performSelector:@selector(addNewImages:) withObject:nil afterDelay:3];
}

-(void)addNewImages:(id)sender {
    newData = [NSMutableArray array];
    int i = 102;
    while (i<111) {
        UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"New_PICT0%d.jpg",i]];
        [newData addObject:image];
        i++;
    }
    [self addNewCells];
}

-(void)addNewCells {
    NSMutableArray *arrayWithIndexPaths = [NSMutableArray array];
    [self.collectionView performBatchUpdates:^{
        int resultsSize = [self.results count];
        [self.results addObjectsFromArray:newData];
        for (int i = resultsSize; i < resultsSize + newData.count; i++)
            [arrayWithIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
        [self.collectionView insertItemsAtIndexPaths:arrayWithIndexPaths];
    }
    completion: ^(BOOL finished){
        [self.collectionView scrollToItemAtIndexPath:arrayWithIndexPaths.lastObject atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:YES];
    }];
}


- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section {
    return [self.results count];
}

- (NSInteger)numberOfSectionsInCollectionView: (UICollectionView *)collectionView {
    return 1;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
    //cell.iv.image = [self.results objectAtIndex:indexPath.row];
    cell.backgroundColor = [UIColor colorWithPatternImage:[self.results objectAtIndex:indexPath.row]];
    return cell;
}


- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    UIImage *image = [self.results objectAtIndex:indexPath.row];
    return CGSizeMake(image.size.width, image.size.height);
}

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    return UIEdgeInsetsMake(10, 10, 90, 10);
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"Selected Image is Item %d",indexPath.row);
}
person rdelmar    schedule 01.10.2012

Установка высоты UICollectionView на 3000 усугубит вашу проблему с прокруткой. Если UICollectionView имеет высоту 3000 пикселей, тогда ему нужно будет прокручивать только в том случае, если в нем содержится контент размером более 3000 пикселей. Вы должны установить его на высоту представления, в котором он содержится (такой же, как и ширина).

Насколько я знаю, также не следует устанавливать contentSize напрямую, вместо этого вам нужно переопределить метод - (CGSize)collectionViewContentSize в подклассе UICollectionViewLayout, но, вообще говоря, вам не нужно изменять размер содержимого для обычного использования.

Я не совсем понимаю, в чем ваша проблема - это то, что когда вы добавляете больше, чем экраны, элементы, которые вы не можете прокручивать?

person simon    schedule 04.10.2012
comment
Это было решением для меня. Я использовал пользовательский макет потока, который удалял вертикальные промежутки между элементами в макете с несколькими столбцами. Я получал только половину предметов, пока не сделал то, что предложил Саймон. Я подозреваю, что причина, по которой у меня возникла проблема, заключается в том, что количество запрашиваемых элементов основано на стандартном макете. - person Matt__C; 15.01.2015

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

Наконец-то я добавил только [self.collectionView reloadData];, и все отлично работает!

Может быть, вы в том же случае.

person dulgan    schedule 07.11.2012