Сохранение содержимогоОфис в UICollectionView при вращении Ориентация интерфейса

Я пытаюсь обрабатывать изменения ориентации интерфейса в UICollectionViewController. То, что я пытаюсь достичь, заключается в том, что я хочу иметь тот же контент, что и после поворота интерфейса. Это означает, что он должен быть изменен в соответствии с отношением изменений границ.

Начиная с портрета с смещением содержимого { bounds.size.width * 2, 0} …

UICollectionView в portait

… должно привести к смещению содержимого в ландшафте также с помощью { bounds.size.width * 2, 0} (и наоборот).

UICollectionView в ландшафте

Вычисление нового смещения не является проблемой, но не знает, где (или когда) установить его, чтобы получить гладкую анимацию. То, что я делаю так, – это недействительность макета в willRotateToInterfaceOrientation:duration: и сброс смещения содержимого в didRotateFromInterfaceOrientation: ::

 - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration; { self.scrollPositionBeforeRotation = CGPointMake(self.collectionView.contentOffset.x / self.collectionView.contentSize.width, self.collectionView.contentOffset.y / self.collectionView.contentSize.height); [self.collectionView.collectionViewLayout invalidateLayout]; } - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation; { CGPoint newContentOffset = CGPointMake(self.scrollPositionBeforeRotation.x * self.collectionView.contentSize.width, self.scrollPositionBeforeRotation.y * self.collectionView.contentSize.height); [self.collectionView newContentOffset animated:YES]; } 

Это изменяет смещение содержимого после вращения.

Как я могу установить его во время вращения? Я попытался установить новое смещение содержимого в willAnimateRotationToInterfaceOrientation:duration: но это приводит к очень странному поведению.

Пример можно найти в моем проекте на GitHub .

22 Solutions collect form web for “Сохранение содержимогоОфис в UICollectionView при вращении Ориентация интерфейса”

Решение 1, «просто щелкнуть»,

Если вам нужно только убедиться, что contentOffset заканчивается в правильном положении, вы можете создать подкласс UICollectionViewLayout и реализовать метод targetContentOffsetForProposedContentOffset : . Например, вы можете сделать что-то подобное, чтобы вычислить страницу:

 - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset { NSInteger page = ceil(proposedContentOffset.x / [self.collectionView frame].size.width); return CGPointMake(page * [self.collectionView frame].size.width, 0); } 

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

Решение 2, «плавная анимация»,

1) Сначала я устанавливаю размер ячейки, которым может управлять метод collectionView: layout: sizeForItemAtIndexPath: delegate следующим образом:

 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { return [self.view bounds].size; } 

Обратите внимание, что [self.view bounds] изменится в соответствии с вращением устройства.

2) Когда устройство вот-вот начнет вращаться, я добавляю imageView поверх представления коллекции со всеми масками для изменения размера. Это представление фактически скроет weirdness collectionView (потому что оно находится поверх него), и поскольку метод willRotatoToInterfaceOrientation: вызывается внутри блока анимации, он будет вращаться соответственно. Я также сохраняю следующее contentOffset в соответствии с показанным indexPath, поэтому я могу исправить contentOffset сразу после его вращения:

 - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { // Gets the first (and only) visible cell. NSIndexPath *indexPath = [[self.collectionView indexPathsForVisibleItems] firstObject]; KSPhotoViewCell *cell = (id)[self.collectionView cellForItemAtIndexPath:indexPath]; // Creates a temporary imageView that will occupy the full screen and rotate. UIImageView *imageView = [[UIImageView alloc] initWithImage:[[cell imageView] image]]; [imageView setFrame:[self.view bounds]]; [imageView setTag:kTemporaryImageTag]; [imageView setBackgroundColor:[UIColor blackColor]]; [imageView setContentMode:[[cell imageView] contentMode]]; [imageView setAutoresizingMask:0xff]; [self.view insertSubview:imageView aboveSubview:self.collectionView]; // Invalidate layout and calculate (next) contentOffset. contentOffsetAfterRotation = CGPointMake(indexPath.item * [self.view bounds].size.height, 0); [[self.collectionView collectionViewLayout] invalidateLayout]; } 

Обратите внимание, что мой подкласс UICollectionViewCell имеет общедоступное свойство imageView.

3) Наконец, последний шаг – «привязать» смещение содержимого к допустимой странице и удалить временное изображение.

 - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { [self.collectionView setContentOffset:contentOffsetAfterRotation]; [[self.view viewWithTag:kTemporaryImageTag] removeFromSuperview]; } 

Ответ «просто щелкнуть» выше не работал для меня, поскольку он часто не заканчивался на предмете, который был в поле зрения перед поворотом. Поэтому я получил макет потока, который использует элемент фокуса (если установлен) для вычисления смещения содержимого. Я установил элемент в willAnimateRotationToInterfaceOrientation и очистил его в didRotateFromInterfaceOrientation. Коррекция вставки, по-видимому, нужна в IOS7, потому что представление Collection может располагаться под верхней панелью.

 @interface HintedFlowLayout : UICollectionViewFlowLayout @property (strong)NSIndexPath* pathForFocusItem; @end @implementation HintedFlowLayout -(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset { if (self.pathForFocusItem) { UICollectionViewLayoutAttributes* layoutAttrs = [self layoutAttributesForItemAtIndexPath:self.pathForFocusItem]; return CGPointMake(layoutAttrs.frame.origin.x - self.collectionView.contentInset.left, layoutAttrs.frame.origin.y-self.collectionView.contentInset.top); }else{ return [super targetContentOffsetForProposedContentOffset:proposedContentOffset]; } } @end 

Для тех, кто использует iOS 8+, willRotateToInterfaceOrientation и didRotateFromInterfaceOrientation устарели.

Теперь вы должны использовать следующее:

 /* This method is called when the view controller's view's size is changed by its parent (ie for the root view controller when its window rotates or is resized). If you override this method, you should either call super to propagate the change to children or manually forward the change to children. */ - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator { [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) { // Update scroll position during rotation animation self.collectionView.contentOffset = (CGPoint){contentOffsetX, contentOffsetY}; } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) { // Whatever you want to do when the rotation animation is done }]; } 

Swift 3:

 override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) coordinator.animate(alongsideTransition: { (context:UIViewControllerTransitionCoordinatorContext) in // Update scroll position during rotation animation }) { (context:UIViewControllerTransitionCoordinatorContext) in // Whatever you want to do when the rotation animation is done } } 

Я считаю, что правильным решением является переопределение (CGPoint) targetContentOffsetForProposedContentOffset: (CGPoint), предлагаемый методContentOffset в подклассе UICollectionViewFlowLayout

Из документов:

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

Эта проблема тоже беспокоила меня. Самый высокий голос, проголосовавший, казался мне слишком взломанным, поэтому я просто немного пошатнул его и просто изменил альфа представления коллекции соответственно до и после ротации. Я также не анимирую обновление содержимого.

 - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { self.collectionView.alpha = 0; [self.collectionView.collectionViewLayout invalidateLayout]; self.scrollPositionBeforeRotation = CGPointMake(self.collectionView.contentOffset.x / self.collectionView.contentSize.width, self.collectionView.contentOffset.y / self.collectionView.contentSize.height); } - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation; { CGPoint newContentOffset = CGPointMake(self.scrollPositionBeforeRotation.x * self.collectionView.contentSize.width, self.scrollPositionBeforeRotation.y * self.collectionView.contentSize.height); [self.collectionView setContentOffset:newContentOffset animated:NO]; self.collectionView.alpha = 1; } 

Довольно гладкий и менее хакерский.

Я использую вариант fz. ответ (iOS 7 и 8):

Перед вращением:

  1. Сохранять текущий видимый путь указателя
  2. Создайте снимок коллекции
  3. Поместите UIImageView с ним поверх представления коллекции

После вращения:

  1. Перейдите к сохраненному индексу
  2. Удалите изображение.

     @property (nonatomic) NSIndexPath *indexPath; - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { self.indexPathAfterRotation = [[self.collectionView indexPathsForVisibleItems] firstObject]; // Creates a temporary imageView that will occupy the full screen and rotate. UIGraphicsBeginImageContextWithOptions(self.collectionView.bounds.size, YES, 0); [self.collectionView drawViewHierarchyInRect:self.collectionView.bounds afterScreenUpdates:YES]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; [imageView setFrame:[self.collectionView bounds]]; [imageView setTag:kTemporaryImageTag]; [imageView setBackgroundColor:[UIColor blackColor]]; [imageView setContentMode:UIViewContentModeCenter]; [imageView setAutoresizingMask:0xff]; [self.view insertSubview:imageView aboveSubview:self.collectionView]; [[self.collectionView collectionViewLayout] invalidateLayout]; } - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { [self.collectionView scrollToItemAtIndexPath:self.indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO]; [[self.view viewWithTag:kTemporaryImageTag] removeFromSuperview]; } 

Вот код в Swift 3.1

 override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) let offset = self.collectionView?.contentOffset; let width = self.collectionView?.bounds.size.width; let index = round(offset!.x / width!); let newOffset = CGPoint(x: index * size.width, y: offset!.y) self.collectionView?.setContentOffset(newOffset, animated: false) coordinator.animate(alongsideTransition: { (context) in self.collectionView?.reloadData() self.collectionView?.setContentOffset(newOffset, animated: false) }, completion: nil) } 

Эта работа как шарм:

 -(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { return self.view.bounds.size; } -(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { int currentPage = collectionMedia.contentOffset.x / collectionMedia.bounds.size.width; float width = collectionMedia.bounds.size.height; [UIView animateWithDuration:duration animations:^{ [self.collectionMedia setContentOffset:CGPointMake(width * currentPage, 0.0) animated:NO]; [[self.collectionMedia collectionViewLayout] invalidateLayout]; }]; } 

После поворота ориентации интерфейса UICollectionViewCell обычно перемещается в другую позицию, потому что мы не будем обновлять contentSize и contentOffset.

Таким образом, видимый UICollectionViewCell всегда не находится в ожидаемом положении.

Видимый UICollectionView, который мы ожидали, как следует

Ориентация, которую мы ожидали

UICollectionView должен делегировать функцию [collectionView sizeForItemAtIndexPath] из 「UICollectionViewDelegateFlowLayout」.

И вы должны рассчитать размер элемента в этой функции.

Пользовательский UICollectionViewFlowLayout должен переопределить функции следующим образом.

  1. -(void)prepareLayout

    , Установите пункт «Размер», «Прокрутка» и другие.

  2. -(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity

    , Рассчитать номер страницы или рассчитать видимое смещение содержимого.

  3. -(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset

    , Возвращение визуального содержимого.

  4. -(CGSize)collectionViewContentSize

    , Верните общий размер содержимого коллекцииView.

Ваш viewController должен переопределить 「willRotateToInterfaceOrientation」, и в этой функции вы должны вызвать функцию [XXXCollectionVew.collectionViewLayout invalidateLayout];

Но 「willRotateToInterfaceOrientation」 устарел в iOS 9 или вы можете вызвать функцию [XXXCollectionVew.collectionViewLayout invalidateLayout] разным способом.

Ниже приведен пример: https://github.com/bcbod2002/CollectionViewRotationTest

Чтобы избавиться от решения troppoli, вы можете установить смещение в своем пользовательском классе, не беспокоясь о том, чтобы помнить о реализации кода в вашем контроллере представления. prepareForAnimatedBoundsChange следует вызывать, когда вы поворачиваете устройство, а затем finalizeAnimatedBoundsChange после его поворота.

 @interface OrientationFlowLayout () @property (strong)NSIndexPath* pathForFocusItem; @end @implementation OrientationFlowLayout - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset { if (self.pathForFocusItem) { UICollectionViewLayoutAttributes* layoutAttrs = [self layoutAttributesForItemAtIndexPath: self.pathForFocusItem]; return CGPointMake(layoutAttrs.frame.origin.x - self.collectionView.contentInset.left, layoutAttrs.frame.origin.y - self.collectionView.contentInset.top); } else { return [super targetContentOffsetForProposedContentOffset:proposedContentOffset]; } } - (void)prepareForAnimatedBoundsChange:(CGRect)oldBounds { [super prepareForAnimatedBoundsChange:oldBounds]; self.pathForFocusItem = [[self.collectionView indexPathsForVisibleItems] firstObject]; } - (void)finalizeAnimatedBoundsChange { [super finalizeAnimatedBoundsChange]; self.pathForFocusItem = nil; } @end 

Если обнаружено, что использование targetContentOffsetForProposedContentOffset не работает во всех сценариях, и проблема с использованием didRotateFromInterfaceOrientation заключается в том, что он дает визуальные артефакты. Мой отличный рабочий код выглядит следующим образом:

 - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; _indexPathOfFirstCell = [self indexPathsForVisibleItems].firstObject; } - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration]; if (_indexPathOfFirstCell) { [UIView performWithoutAnimation:^{ [self scrollToItemAtIndexPath:self->_indexPathOfFirstCell atScrollPosition:UICollectionViewScrollPositionTop animated:NO]; }]; _indexPathOfFirstCell = nil; } } 

Ключ заключается в использовании метода willRotateToInterfaceOrientation для определения части в представлении, которую вы хотите прокрутить, и willAnimationRotationToInterfaceOrientation, чтобы пересчитать его, когда представление изменило его размер (оценки уже изменились, когда этот метод вызывается каркасом) и фактически прокрутите до новой позиции без анимации. В моем коде я использовал указательный путь для первой визуальной ячейки, но процент контента contentOffset.y / contentSize.height также будет выполнять работу несколько иначе.

Возможно, вам захочется скрыть коллекциюView во время ее (неправильной) анимации и показать вид замещающей ячейки ячейки, которая вращается правильно.

Для простой фотогалереи я нашел способ сделать это, что выглядит неплохо. См. Мой ответ здесь: Как повернуть UICollectionView, подобный приложению для фотографий, и сохранить текущий центр в центре?

Мой способ – использовать объект UICollectionViewFlowlayout.

Задайте расстояние между строками ojbect, если оно прокручивается горизонтально.

 [flowLayout setMinimumLineSpacing:26.0f]; 

Задайте интерэйт-интервал, если он прокручивается вертикально.

 [flowLayout setMinimumInteritemSpacing:0.0f]; 

Обратите внимание, что при повороте экрана поведение ведет себя по-другому. В моем случае, я прокручиваю его горизонтально, так что минимальное расстояние составляет 26.0f. Тогда это кажется ужасным, когда он вращается в ландшафтном направлении. Я должен проверить вращение и установить минимальное расстояние для этого направления 0.0f, чтобы сделать это правильно.

Это оно! Просто.

У меня была проблема с моим проектом, я использовал два разных макета для UICollectionView.

 mCustomCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"LandScapeCell" forIndexPath:indexPath]; theCustomCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"PortraitCell" forIndexPath:indexPath]; 

Затем проверьте его для каждой ориентации и используйте свою конфигурацию для каждой ориентации.

 -(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { CGSize pnt = CGSizeMake(70, 70); return pnt; } -(UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { // UIEdgeInsetsMake(<#CGFloat top#>, <#CGFloat left#>, <#CGFloat bottom#>, <#CGFloat right#>) return UIEdgeInsetsMake(3, 0, 3, 0); } 

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

Используйте <CollectionViewDelegateFlowLayout> и в методе didRotateFromInterfaceOrientation: перезагрузите данные CollectionView.

Внедрите <CollectionViewDelegateFlowLayout> collectionView:layout:sizeForItemAtIndexPath: метод <CollectionViewDelegateFlowLayout> и в этом методе проверьте ориентацию интерфейса и примените свой собственный размер каждой ячейки.

 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; if (UIInterfaceOrientationIsPortrait(orientation)) { return CGSizeMake(CGFloat width, CGFloat height); } else { return CGSizeMake(CGFloat width, CGFloat height); } } 

У меня есть аналогичный случай, когда я использую этот

 - (void)setFrame:(CGRect)frame { CGFloat currentWidth = [self frame].size.width; CGFloat offsetModifier = [[self collectionView] contentOffset].x / currentWidth; [super setFrame:frame]; CGFloat newWidth = [self frame].size.width; [[self collectionView] setContentOffset:CGPointMake(offsetModifier * newWidth, 0.0f) animated:NO]; } 

Это представление, которое содержит collectionView. В супервизии я тоже это делаю

 - (void)setFrame:(CGRect)frame { UICollectionViewFlowLayout *collectionViewFlowLayout = (UICollectionViewFlowLayout *)[_collectionView collectionViewLayout]; [collectionViewFlowLayout setItemSize:frame.size]; [super setFrame:frame]; } 

Это необходимо для настройки размеров ячеек в полноэкранном режиме (полный просмотр будет точным;)). Если вы этого не сделаете, может появиться много сообщений об ошибках, что размер ячейки больше, чем коллекция, и что поведение для этого не определено и bla bla bla …..

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

Ответ «просто щелкнуть» – это правильный подход и не требует дополнительного сглаживания с помощью наложений IMO. Однако есть проблема, которая объясняет, почему некоторые люди видят, что в некоторых случаях правильная страница не прокручивается. При расчете страницы вы хотите использовать высоту, а не ширину. Зачем? Поскольку геометрия представления уже повернута к моменту достижения цели targetContentOffsetForProposedContentOffset, и, следовательно, какая ширина была теперь высотой. Также округление более разумно, чем потолок. Так:

 - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset { NSInteger page = round(proposedContentOffset.x / self.collectionView.bounds.size.height); return CGPointMake(page * self.collectionView.bounds.size.width, 0); } 

Что для меня эта работа:

  1. Установите размер моих ячеек из моего метода UICollectionViewDelegateFlowLayout

     func collectionView(collectionView: UICollectionView!, layout collectionViewLayout: UICollectionViewLayout!, sizeForItemAtIndexPath indexPath: NSIndexPath!) -> CGSize { return collectionView.bounds.size } 
  2. После этого я реализую willRotateToInterfaceOrientationToInterfaceOrientation:duration: like this

     override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) { let currentPage = Int(collectionView.contentOffset.x / collectionView.bounds.size.width) var width = collectionView.bounds.size.height UIView.animateWithDuration(duration) { self.collectionView.setContentOffset(CGPointMake(width * CGFloat(currentPage), 0.0), animated: false) self.collectionView.collectionViewLayout.invalidateLayout() } } 

Вышеприведенный код находится в Swift, но вы поняли, что его легко перевести,

Я решил эту проблему следующими шагами:

  1. Вычислить в настоящее время прокрутку NSIndexPath
  2. Отключить прокрутку и разбиение на страницы в UICollectionView
  3. Применить новый макет потока к UICollectionView
  4. Включить прокрутку и разбиение на страницы в UICollectionView
  5. Прокрутите UICollectionView до текущего NSIndexPath

Вот шаблон кода, демонстрирующий следующие шаги:

 - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration; { //Calculating Current IndexPath CGRect visibleRect = (CGRect){.origin = self.yourCollectionView.contentOffset, .size = self.yourCollectionView.bounds.size}; CGPoint visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect)); self.currentIndexPath = [self.yourCollectionView indexPathForItemAtPoint:visiblePoint]; //Disable Scrolling and Pagination [self disableScrolling]; //Applying New Flow Layout [self setupNewFlowLayout]; //Enable Scrolling and Pagination [self enableScrolling]; } - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation; { //You can also call this at the End of `willRotate..` method. //Scrolling UICollectionView to current Index Path [self.yourCollectionView scrollToItemAtIndexPath:self.currentIndexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:NO]; } - (void) disableScrolling { self.yourCollectionView.scrollEnabled = false; self.yourCollectionView.pagingEnabled = false; } - (void) enableScrolling { self.yourCollectionView.scrollEnabled = true; self.yourCollectionView.pagingEnabled = true; } - (void) setupNewFlowLayout { UICollectionViewFlowLayout* flowLayout = [[UICollectionViewFlowLayout alloc] init]; flowLayout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0); flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; flowLayout.minimumInteritemSpacing = 0; flowLayout.minimumLineSpacing = 0; [flowLayout setItemSize:CGSizeMake(EXPECTED_WIDTH, EXPECTED_HEIGHT)]; [self.yourCollectionView setCollectionViewLayout:flowLayout animated:YES]; [self.yourCollectionView.collectionViewLayout invalidateLayout]; } 

Надеюсь, это поможет.

в Свифт 3.

вы должны отслеживать, какой элемент ячейки (страница) отображается перед вращением с помощью indexPath.item, координаты x или что-то еще. Затем в вашем UICollectionView:

 override func collectionView(_ collectionView: UICollectionView, targetContentOffsetForProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint { let page:CGFloat = pageNumber // your tracked page number eg. 1.0 return CGPoint(x: page * collectionView.frame.size.width, y: -(topInset)) //the 'y' value would be '0' if you don't have any top EdgeInset } 

В моем случае я недействителен макет в viewDidLayoutSubviews (), поэтому collectionView.frame.size.width – это ширина отображаемого вида collectionVC.

Возможно, вы захотите попробовать этот непроверенный код:

 - (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) toInterfaceOrientation duration: (NSTimeInterval) duration { [UIView animateWithDuration: duration animation: ^(void) { CGPoint newContentOffset = CGPointMake(self.scrollPositionBeforeRotation.x * self.collectionView.contentSize.height, self.scrollPositionBeforeRotation.y * self.collectionView.contentSize.width); [self.collectionView setContentOffset: newContentOffset animated: YES]; }]; } 
  • Вертикальная прокрутка не работает в UIScrollView и iOS7 и Xcode 5, несмотря на то, что не используется Autolayout
  • iPhone - знание, если UIScrollView достиг верхней или нижней
  • скрыть клавиатуру при касании вида прокрутки
  • Почему UIScrollView нельзя прокручивать в iOS-симуляторе?
  • Как точно знать, когда прокрутка UIScrollView прекратилась?
  • UIScrollView Direction RTL для языков справа налево
  • Режим передачи голоса - прокрутка к просмотрам, которые не отображаются в прокрутке.
  • Горизонтальная или вертикальная прокрутка, но не обе
  • iOS: изменение позиции изображения при прокрутке в / из просмотра
  • didSelectRowAtIndexPath вызывается после долгого нажатия
  • Получите расстояние между двумя CGPoints в UIImageView, вложенном в UIScrollView
  • iOS UIScrollView с поддержкой голоса
  • PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.