2013-04-13 8 views
76

Перед загрузкой коллекции пользователь устанавливает количество изображений в массиве просмотра коллекции. Все ячейки не помещаются на экране. У меня 30 ячеек и только 6 на экране.UICollectionView автоматический прокрутка к ячейке в IndexPath

Вопрос: Как автоматически перейти к ячейке с желаемым изображением при загрузке UICollectionView?

ответ

136

Новый, под редакцией Ответ:

Добавить это в viewDidLayoutSubviews

-(void)viewDidLayoutSubviews { 
    [super viewDidLayoutSubviews]; 
    [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:NO]; 
} 

Старый ответ работает на старых прошивкой

Добавить это в viewWillAppear:

[self.view layoutIfNeeded]; 
[self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:NO]; 
+4

Это именно то, что я пытаюсь использовать. У меня есть номер объекта в массиве, и я знаю имя этого объекта. Но не знаете, как правильно поставить indexPath ... Любые идеи? – AlexanderZ

+4

Вы можете легко создать 'indexPath':' [NSIndexPath indexPathForItem: numberOfTheObject inSection: sectionNumber] ' –

+3

Были ошибки. Но тогда я поместил весь упомянутый код внутри (void) viewDidLayoutSubviews {}, и теперь он работает нормально. Тханкс Богдан. – AlexanderZ

13

Я полностью согласен с приведенным выше ответом. Единственное, что для меня решение было установить код в viewDidAppear

viewDidAppear 
{ 
    [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:YES]; 
} 

Когда я использовал viewWillAppear скроллинг не работал.

+0

i секунду это !! – Mike

+1

viewDidAppear имеет тот недостаток, что вы видите, что просмотр коллекции перемещается/мигает, представление уже появилось (как следует из названия) ... Я действительно удивляюсь, почему Apple не разработала этот не очень необычный случай в лучшую сторону, путь viewDidLayoutSubviews немного неудобно – TheEye

68

Я нашел, что прокрутка в viewWillAppear может не работать надежно, потому что представление коллекции еще не закончило его компоновку; вы можете прокрутить не тот элемент.

Я также обнаружил, что прокрутка в viewDidAppear приведет к тому, что мгновенная вспышка не просматриваемого вида будет видимой.

И, если вы прокручиваете каждый раз через viewDidLayoutSubviews, пользователь не сможет прокручивать вручную, потому что некоторые макеты коллекции вызывают макет под просмотр при каждом прокрутке.

Вот что я нашел работает надежно:

- (void)viewDidLayoutSubviews { 
    [super viewDidLayoutSubviews]; 

    // If we haven't done the initial scroll, do it once. 
    if (!self.initialScrollDone) { 
     self.initialScrollDone = YES; 

     [self.collectionView scrollToItemAtIndexPath:self.myInitialIndexPath 
            atScrollPosition:UICollectionViewScrollPositionRight animated:NO]; 
    } 
} 
+0

Хороший совет. Я буду подчеркивать использование флага 'initialScrollDone', поскольку LenK сделал это, потому что этот метод будет вызван более одного раза, и если вы вызовете scrollToItemAtIndexPath: более чем один раз кажется, что он отображает unViewrollable (iOS simulator iPhone 5/iOS 8) – maz

+1

thx , это должен быть принятый ответ – Jakob

+1

Отлично работает в iOS8. Должен быть принятый ответ. – Nick

11

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

- (void)viewDidLayoutSubviews 
{  
    [self.collectionView layoutIfNeeded]; 
    NSArray *visibleItems = [self.collectionView indexPathsForVisibleItems]; 
    NSIndexPath *currentItem = [visibleItems objectAtIndex:0]; 
    NSIndexPath *nextItem = [NSIndexPath indexPathForItem:someInt inSection:currentItem.section]; 

    [self.collectionView scrollToItemAtIndexPath:nextItem atScrollPosition:UICollectionViewScrollPositionNone animated:YES]; 
} 
10

Swift:

your_CollectionView.scrollToItemAtIndexPath(indexPath, atScrollPosition: UICollectionViewScrollPosition.CenteredHorizontally, animated: true) 

Swift 3

let indexPath = IndexPath(row: itemIndex, section: sectionIndex) 

collectionView.scrollToItem(at: indexPath, at: UICollectionViewScrollPosition.right, animated: true) 

Прокрутка Должность:

UICollectionViewScrollPosition.CenteredHorizontally/UICollectionViewScrollPosition.CenteredVertically 
7

Вы можете использовать НОД для отправки свитки в следующую итерацию основного цикла выполнения в viewDidLoad для достижения такого поведения. Прокрутка будет выполняться до отображения вида коллекции на экране, поэтому мигание не будет.

- (void)viewDidLoad { 
    dispatch_async (dispatch_get_main_queue(), ^{ 
     NSIndexPath *indexPath = YOUR_DESIRED_INDEXPATH; 
     [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO]; 
    }); 
} 
+0

Это был единственный подход, который работал для меня –

0

Все ответы здесь - хаки.Я нашел лучший способ прокрутки просмотра коллекции где-то после relaodData:
Представление подкласса коллекции, какой бы макет вы не использовали, переопределить метод prepareLayout, после того, как супер-вызов установил то, что когда-либо было необходимо вам.
например: https://stackoverflow.com/a/34192787/1400119

0

Я рекомендовал бы это делать в collectionView: willDisplay: Тогда вы можете быть уверены в том, что вид коллекции делегат доставляет что-то. Здесь мой пример:

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { 
    /// this is done to set the index on start to 1 to have at index 0 the last image to have a infinity loop 
    if !didScrollToSecondIndex { 
     self.scrollToItem(at: IndexPath(row: 1, section: 0), at: .left, animated: false) 
     didScrollToSecondIndex = true 
    } 
}