Проблема с нумерацией страниц в UICollectionView при изменении ориентации

введите здесь описание изображениявведите здесь описание изображения
Я готовлю GridView со всей поддержкой ориентации (изменение размеров по высоте и ширине) и включенным разбиением по страницам.

В моем примере я взял сетку 3 * 3 и, чтобы показать ее так, я добавил несколько фиктивных прозрачных ячеек на последней странице.

Проблема в том, что когда я нахожусь на последней странице и меняю ориентацию с альбомной на портретную, нумерация страниц не работает.

Я использовал этот код в willRotateToInterfaceOrientation:

CGPoint scrollTo = CGPointMake(self.frame.size.width * mPageControl.currentPage, 0);
[self setContentOffset:scrollTo animated:YES];

Но все равно страница перемещается на страницу перед последней страницей при переходе с альбомной на портретную, а при смене портретной на альбомную все работает нормально.


person Arun_    schedule 06.09.2013    source источник


Ответы (3)


Была та же проблема, мой UICollectionView был разбит на страницы, когда я прокручивал страницу 2 в портретном режиме, а затем переключался на ландшафт, смещение содержимого было установлено на (72, 0), и это сохранялось.

Контроллер был зарегистрирован для изменения ориентации, что сделало макет недействительным, но установка смещения не помогла.

Что помогло, так это установка смещения в методе prepareForLayout класса макета. я использовал

self.collectionView.contentOffset = CGPointMake(ceil(self.collectionView.contentOffset.x/self.collectionView.frame.size.width)*self.collectionView.frame.size.width, self.collectionView.contentOffset.y);

Потолок используется, потому что пол всегда будет возвращаться на предыдущую страницу (а страница 0 всегда нормально разбивается на страницы).

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

person meelawsh    schedule 10.12.2013
comment
Даже я тоже пробовал это, и это сработало. + 1 голос за ваши усилия. - person Arun_; 11.12.2013
comment
Я столкнулся с той же проблемой, показывая только одну ячейку за раз в представлении коллекции с горизонтальной прокруткой, ваш ответ спас мне день. Однако я столкнулся с проблемой неправильного отображения ячеек при вращении устройства, чтобы исправить это, я реализовал метод подготовки, как показано ниже в комментарии... - person Devarshi; 14.04.2019
comment
переопределить func prepare() { охранять let collectionView = collectionView, let indexPath = collectionView.indexPathsForVisibleItems.last else { return } let xOffset = ceil(CGFloat(indexPath.row) * collectionView.frame.size.width) let yOffset = collectionView.contentOffset .y collectionView.contentOffset = CGPoint(x: xOffset, y: yOffset) } - person Devarshi; 14.04.2019

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

var cellWidthInLandscape: CGFloat = 0 {
    didSet {
        self.collectionView.reloadData()
    }
}

var lastIndex: Int = 0

override func viewDidLoad() {
    super.viewDidLoad()

    collectionView.dataSource = self
    collectionView.delegate = self
    NotificationCenter.default.addObserver(self, selector: #selector(rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
    cellWidthInLandscape = UIScreen.main.bounds.size.width

}
deinit {
    NotificationCenter.default.removeObserver(self)
}
@objc func rotated() {

        // Setting new width on screen orientation change
        cellWidthInLandscape = UIScreen.main.bounds.size.width

       // Setting collectionView to previous indexpath
        collectionView.scrollToItem(at: IndexPath(item: lastIndex, section: 0), at: .right, animated: false)
}
    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        NotificationCenter.default.addObserver(self, selector: #selector(rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)

}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {

   // Getting last contentOffset to calculate last index of collectionViewCell
    lastIndex = Int(scrollView.contentOffset.x / collectionView.bounds.width)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        // Setting new width of collectionView Cell
        return CGSize(width: cellWidthInLandscape, height: collectionView.bounds.size.height)

}
person Yubraj Basyal    schedule 03.10.2018

UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];

    //Ignoring specific orientations
    if (orientation == UIDeviceOrientationFaceUp || orientation == UIDeviceOrientationFaceDown || orientation == UIDeviceOrientationUnknown || currentOrientation == orientation)
    {
        return;
    }
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(relayoutLayers) object:nil];
    //Responding only to changes in landscape or portrait
    currentOrientation = orientation;

    [self performSelector:@selector(handleOrientationChange) withObject:nil afterDelay:0];

Затем я вызываю метод всякий раз, когда меняется ориентация

-(void)handleOrientationChange
{
    CGRect frame = self.frame;
    frame.origin.x = self.frame.size.width * mPageControl.currentPage;
    frame.origin.y = 0;
    [self scrollRectToVisible:frame animated:YES];
}
person Arun_    schedule 04.10.2013