简体   繁体   English

方向更改时UICollectionView中的分页问题

[英]Issue with pagination in UICollectionView when orientation changes

在此处输入图片说明在此处输入图片说明
I'm preparing a GridView with all orientation support (height & width resizing) and paging enabled. 我正在准备一个具有所有方向支持(调整高度和宽度大小)和分页的GridView。

In my sample in have taken a 3*3 Grid and to show it like that I have added some dummy transparent cell at the last page. 在我的示例中,采用了3 * 3网格,并以此进行显示,在最后一页中添加了一些虚拟透明单元格。

The issue is when I'm at last page and there I'm changing my orientation from landscape to portrait the pagination doesn't work. 问题是当我到达最后一页时,我将方向从横向更改为纵向,因此分页不起作用。

I have used this code in willRotateToInterfaceOrientation : 我在willRotateToInterfaceOrientation使用了以下代码:

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

But still page moves to a page before the last page when going from landscape to portrait and while changing portrait to landscape it works fine. 但是,当从横向到纵向以及将纵向改为横向时,静止页面都移动到最后一页之前的页面。

Had the same problem, my UICollectionView was paginated, when I scrolled to page 2 in portrait mode and then switched to landscape, the content offset would be set to (72, 0), and this would persist. 遇到相同的问题,我的UICollectionView是分页的,当我在纵向模式下滚动到页面2然后切换到横向时,内容偏移将设置为(72,0),并且这种情况将持续存在。

The controller was registered for orientation changes where it invalidated the layout, but setting the offset in there didn't help. 控制器已注册以更改方向,从而使布局无效,但在其中设置偏移量没有帮助。

What did help was setting the offset inside the layout class' prepareForLayout method. 没有什么帮助下设置布局类的内部偏移prepareForLayout方法。 I used 我用了

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

Ceiling is used because floor would always go back to the previous page (and page 0 always paginates fine). 使用天花板是因为地板将始终返回到上一页(并且页面0总是分页良好)。

If you're not using a custom layout, you can still subclass flow layout and override that one function. 如果您不使用自定义布局,则仍然可以继承流布局并覆盖该功能。

I manage to solve this by setting notification when screen orientation changes and reloading cell which set itemsize according to screen orientation and setting indexpath to previous cell. 我设法通过在屏幕方向更改时设置通知并重新加载根据屏幕方向设置项目大小并为上一个单元格设置索引路径的单元格来解决此问题。 This does work with flowlayout too. 这也适用于flowlayout。 Here is the code i wrote: 这是我写的代码:

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)

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

Then i'm calling a method whenever orientation is changing 然后每当方向改变时我就调用一个方法

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM