旋转后在 UICollectionView 中保留第一个可见项目
Posted
技术标签:
【中文标题】旋转后在 UICollectionView 中保留第一个可见项目【英文标题】:Keep first visible item in UICollectionView after rotation 【发布时间】:2014-10-14 01:51:38 【问题描述】:我在其他 *** 问题中搜索了答案,但找不到以下问题的任何解决方案:
我正在尝试使用带有流式布局(垂直)的 UICollectionView,并使项目大小取决于屏幕大小(它应该利用 iPad 的宽度,甚至在横向时利用 iPhone 的宽度)。
我想让 UICollectionView 在纵向 iPhone 上只显示一列项目,但在横向 iPhone 上显示 2 列。当然,让它变得通用,这样如果有更多的水平空间可用,它也可以显示更多的列,例如在 iPad 中。
为了实现这种行为,我做了以下操作:
- (void)viewWillLayoutSubviews
[super viewWillLayoutSubviews];
UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
NSInteger columns = 1 + ((NSInteger)(CGRectGetWidth(self.collectionView.frame) - layout.sectionInset.left - layout.sectionInset.right + layout.minimumInteritemSpacing)) / ((NSInteger)(layout.minimumInteritemSpacing + 300.0 + 1.0));
layout.itemSize = CGSizeMake((CGRectGetWidth(self.collectionView.frame) - layout.sectionInset.left - layout.sectionInset.right - ((columns - 1) * layout.minimumInteritemSpacing)) / columns, layout.itemSize.height);
[layout invalidateLayout];
这很好用,当我旋转手机时,我可以看到布局显示两列而不是一列。
但我无法让 UICollectionView 在旋转后保留第一个可见项目,因为它将内容偏移设置为旋转之前的任何内容。随着布局的改变,现在 UICollectionView 在横向上显示两列,这个新的内容偏移应该有一个新值,它对应于同一个项目,但在一个新的布局下。
我尝试使用以下 sn-p,但没有成功:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
NSIndexPath *firstAddShowCellIndexPath = [[[self.collectionView indexPathsForVisibleItems] sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2)
NSIndexPath *ip1 = obj1;
NSIndexPath *ip2 = obj2;
return [ip1 compare:ip2];
] firstObject];
if (firstAddShowCellIndexPath)
[self.collectionView scrollToItemAtIndexPath:firstAddShowCellIndexPath atScrollPosition:UICollectionViewScrollPositionTop animated:YES];
我怀疑 UICollectionView 正在尝试处理旋转期间的内容偏移,所以我什至尝试使用 dispatch_after
或 willRotateToInterfaceOrientation
,但虽然它确实有效,但它在旋转完成后将内容偏移设置为延迟,给出非常糟糕的用户体验。
有什么想法吗?
谢谢大家!
【问题讨论】:
【参考方案1】:这对我有用,
添加此方法而不是 willRotation
方法
#pragma mark - Rotation
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
[self.collectionView.collectionViewLayout invalidateLayout];
作为一个例子,这是我在旋转前后制作两个列的快速代码,等等
#pragma mark <UICollectionViewDelegateFlowLayout>
- (CGSize)collectionView:(UICollectionView *)collectionView layout(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath*)indexPath
int width = roundf(self.collectionView.frame.size.width / 2.0) - 15;
int height = roundf(width * 0.8);
return CGSizeMake(width, height);
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
UIEdgeInsets new = UIEdgeInsetsMake(10, 10, 10, 10);
return new;
【讨论】:
以上是关于旋转后在 UICollectionView 中保留第一个可见项目的主要内容,如果未能解决你的问题,请参考以下文章
UICollectionView 在 reloadData 后在屏幕外崩溃时崩溃
屏幕旋转后如何在 UICollectionView 中跟踪单元格的移动