Ios 更改不同设备方向上的UICollectionViewCell大小

Ios 更改不同设备方向上的UICollectionViewCell大小,ios,uicollectionview,uicollectionviewcell,Ios,Uicollectionview,Uicollectionviewcell,我将UICollectionView与UICollectionViewFlowLayout一起使用 我通过 collectionView:layout:sizeForItemAtIndexPath: 当从纵向切换到横向时,我想调整每个单元格的大小,以完全适合CollectionView的大小,而不在单元格之间留下填充空间 问题: 1) 如何在旋转事件后更改单元格的大小 2) 还有,更好的是,如何使单元格始终适合整个屏幕大小的布局?我使用两个UICollectionViewFlowLayout解

我将
UICollectionView
UICollectionViewFlowLayout
一起使用

我通过

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

问题:

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


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

我使用两个UICollectionViewFlowLayout解决了这个问题。一个是肖像画,一个是风景画。我将它们分配到我的收藏视图中,并在-viewDidLoad中进行编辑

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];
    }
}
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];
}
调用
-performbatchudates:completion:
将使布局无效,并通过动画调整单元格大小(如果没有额外的调整要执行,则可以将nil传递给两个块参数)


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

如果您不想通过执行更新:完成:带来额外的动画,只需使用
invalidateLayout
强制重新加载collectionViewLayout即可

- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];
    [self.collectionView.collectionViewLayout invalidateLayout];
}

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

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

但不确定它是否可设置动画。

如果使用的是
自动布局
。旋转时,只需在视图控制器中
使布局无效,并在流布局子类中调整
偏移量

因此,在您的视图控制器中-

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

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

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)
}

为什么不直接调用
[self.collectionView.collectionViewLayout invalidateLayout]
?@user102008调用
invalidateLayout
将重新绘制大小正确的单元格,但
-performbatchUpdate:completion:
将设置更改的动画,在我看来,在我滚动屏幕之前,代码不会调整collectionviewcell的大小。
didRotateFromInterfaceOrientation
在iOS 8上不推荐使用,我正在调用
coordinator.AnimateLongSideTransition
中的
ViewWillTransitionOnToSize
,并在其
动画
块内调用
performbatchUpdate
。这提供了一个很好的动画效果。followben的答案目前被接受,但它有一些问题:它会抛出一个控制台错误,并且新大小的动画不会正确发生。有关正确的实现,请参阅我的答案。@MichaelG.Emmons:如果集合视图一次只显示一个完整大小的单元格,则您的答案会更有效。在这种情况下,UIKit在调用
didRotateFromInterfaceOrientation
之前查询
sizeForiteIndeXPath
时会抱怨旋转是有道理的。但是,对于屏幕上有多个单元格的集合视图,在旋转前使布局无效会导致视图旋转前尺寸急剧增大。在这种情况下,我相信我的答案仍然是最正确的实现。@followben同意每种方法在不同的用例中都有各自的问题。不过,在这种情况下,OP表示
我想调整每个单元格的大小**完全适合CollectionView**
的大小,这正是我在回答中提出的解决方案。如果你能在你的答案中包含我的解决方案,并记下哪种方法在哪种条件下最有效,这对我来说已经足够好了。我不得不在viewWillLayoutSubviews的内部使用这一点,高海峰的回答是:这非常有效
willRotateToInterfaceOrientation
在iOS 8中被弃用,但对于这一点,
ViewWillTransitionoSize
也同样适用。