100

我正在使用UICollectionViewwith UICollectionViewFlowLayout

我通过设置每个单元格的大小

collectionView:layout:sizeForItemAtIndexPath:

从纵向切换到横向时,我想调整每个单元格的大小以完全适合 CollectionView 的大小,而不会在单元格之间留下填充空间。

问题:

1)如何在旋转事件后更改单元格的大小?

2)而且,更好的是,如何使单元格始终适合整个屏幕大小的布局?

4

6 回答 6

201

1)您可以维护和交换多个布局对象,但有一种更简单的方法。只需将以下内容添加到您的UICollectionViewController子类并根据需要调整大小:

- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout *)collectionViewLayout
  sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{    
    // Adjust cell size for orientation
    if (UIDeviceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
        return CGSizeMake(170.f, 170.f);
    }
    return CGSizeMake(192.f, 192.f);
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    [self.collectionView performBatchUpdates:nil completion:nil];
}

调用-performBatchUpdates:completion:将使布局无效并使用动画调整单元格的大小(如果您没有要执行的额外调整,您可以将 nil 传递给两个块参数)。

2) 无需在 中硬编码项目大小-collectionView:layout:sizeForItemAtIndexPath,只需将 collectionView 边界的高度或宽度除以您希望在屏幕上显示的单元格数即可。如果您的 collectionView 水平滚动,则使用高度;如果垂直滚动,则使用宽度。

于 2012-12-01T05:10:24.567 回答
33

如果不希望 带来额外的动画performBatchUpdates:completion:,只需使用invalidateLayout强制 collectionViewLayout 重新加载即可。

- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];
    [self.collectionView.collectionViewLayout invalidateLayout];
}
于 2013-02-08T16:20:31.773 回答
13

我使用两个 UICollectionViewFlowLayout 解决了。一张是纵向的,一张是横向的。我在 -viewDidLoad 中动态地将它们分配给我的 collectionView

self.portraitLayout = [[UICollectionViewFlowLayout alloc] init];
self.landscapeLayout = [[UICollectionViewFlowLayout alloc] init];

UIInterfaceOrientation orientationOnLunch = [[UIApplication sharedApplication] statusBarOrientation];

if (UIInterfaceOrientationIsPortrait(orientationOnLunch)) {
    [self.menuCollectionView setCollectionViewLayout:self.portraitLayout];
} else {
    [self.menuCollectionView setCollectionViewLayout:self.landscapeLayout];
}

然后我像这样简单地修改了我的 collectionViewFlowLayoutDelgate 方法

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
    CGSize returnSize = CGSizeZero;

    if (collectionViewLayout == self.portraitLayout) {
        returnSize = CGSizeMake(230.0, 120.0);
    } else {
        returnSize = CGSizeMake(315.0, 120.0);
    }

    return returnSize;
}

最后我在旋转时从一个布局切换到另一个

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
    if (UIInterfaceOrientationIsPortrait(fromInterfaceOrientation)) {
        [self.menuCollectionView setCollectionViewLayout:self.landscapeLayout animated:YES];
    } else {
        [self.menuCollectionView setCollectionViewLayout:self.portraitLayout animated:YES];
    }
}
于 2012-11-28T13:38:21.120 回答
8

有一种设置集合视图单元格大小的简单方法:

UICollectionViewFlowLayout *layout = (id) self.collectionView.collectionViewLayout;
layout.itemSize = CGSizeMake(cellSize, cellSize);

不确定它是否是可动画的。

于 2014-05-31T15:21:24.100 回答
7

Swift:集合视图单元格是屏幕高度的 n%

我需要的是一个占视图高度一定百分比的单元格,并且会随着设备旋转而调整大小。

在上面的帮助下,这是解决方案

override func viewDidLoad() {
    super.viewDidLoad()
    automaticallyAdjustsScrollViewInsets = false
    // if inside nav controller set to true
}

override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
    collectionViewLayout.invalidateLayout()
}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    return CGSize(width: 100, height: collectionView.frame.height * 0.9)
}
于 2015-11-07T23:23:36.753 回答
2

如果您正在使用autolayout。您只需要invalidate layout在您的视图控制器中旋转和调整offset您的流布局子类。

所以,在你的视图控制器中 -

override func willRotateToInterfaceOrientation(toInterfaceOrientation:     UIInterfaceOrientation, duration: NSTimeInterval) {
    self.galleryCollectionView.collectionViewLayout.invalidateLayout()
}

在你的FlowLayout Subclass

override func prepareLayout() {
    if self.collectionView!.indexPathsForVisibleItems().count > 0{
    var currentIndex : CGFloat!
    currentIndex = CGFloat((self.collectionView!.indexPathsForVisibleItems()[0] as! NSIndexPath).row)
    if let currentVal = currentIndex{
        self.collectionView!.contentOffset = CGPointMake(currentIndex * self.collectionView!.frame.width, self.collectionView!.contentOffset.y);
    }   
    }     
}
于 2015-08-16T11:43:40.350 回答