当屏幕方向改变时,UICollectionView分页出现问题

5

输入图像描述 输入图像描述
我正在准备一个支持所有方向(高度和宽度调整)且启用分页的GridView。

在我的示例中,我使用了3*3网格,并添加了一些虚拟透明单元格来显示它。但是,在最后一页并将方向从横向更改为纵向时,分页不起作用。

我在willRotateToInterfaceOrientation中使用了以下代码:

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

但是,当从横向模式切换到纵向模式时,页面仍然会跳转到倒数第二页,而在从纵向模式切换到横向模式时,它能够正常工作。

3个回答

4

我曾经遇到了同样的问题。我的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);

使用Ceiling是因为floor总是返回到上一页(而页面0始终分页良好)。

如果您不使用自定义布局,则仍可以子类化流式布局并覆盖该函数。


我也尝试过这个,它有效。为你的努力点赞+1。 - Arun_
我在水平滚动的集合视图中只显示一个单元格时也遇到了同样的问题,你的答案救了我的一天。然而,当设备旋转时,我遇到了不正确的单元格显示问题,为了解决它,我实现了下面注释中的 prepare 方法... - Devarshi
重写函数准备() { guard 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) } - Devarshi

1
我通过在屏幕方向更改时设置通知并重新加载单元格来解决了这个问题,该单元格根据屏幕方向设置项目大小,并将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)

}

0
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];
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接