【问题标题】:Change UICollectionViewCell size on different device orientations在不同设备方向上更改 UICollectionViewCell 大小
【发布时间】:2012-11-13 10:33:53
【问题描述】:

我正在使用 UICollectionViewUICollectionViewFlowLayout

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

collectionView:layout:sizeForItemAtIndexPath:

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

问题:

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

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

【问题讨论】:

  • followben 的回答目前已被接受,但它有一些问题:它会引发控制台错误,并且新尺寸的动画不会正确发生。请参阅我的答案以了解正确的实施方式。
  • @MichaelG.Emmons:如果集合视图一次只显示一个完整大小的单元格,您的答案会更好。在这种情况下,UIKit 抱怨旋转是有道理的,因为它会在调用didRotateFromInterfaceOrientation 之前查询sizeForItemAtIndexPath。但是,对于屏幕上有多个单元格的集合视图,在旋转之前使布局无效会导致在视图旋转之前出现令人讨厌的、可见的尺寸跳跃。在那种情况下,我相信我的答案仍然是最正确的实现。
  • @followben 同意每个人在不同的用例中都有自己的问题。但在这种情况下,OP 表示 I would like to adjust the size of each cell to **completely fit the size of the CollectionView** 这正是我在回答中提出的解决方案。如果您可以在答案中包含我的解决方案,并记下哪种方法在哪种条件下对我来说效果最好。

标签: ios uicollectionview uicollectionviewcell


【解决方案1】:

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 水平滚动,则使用高度;如果垂直滚动,则使用宽度。

【讨论】:

  • 为什么不直接打电话给[self.collectionView.collectionViewLayout invalidateLayout];
  • @user102008 调用invalidateLayout 将重新绘制具有正确大小的单元格,但-performBatchUpdates:completion: 将为更改设置动画,恕我直言,这看起来好多了。
  • 在我的情况下,代码不会调整 collectionviewcell 的大小,直到我滚动屏幕。
  • didRotateFromInterfaceOrientation 在 iOS 8 中已弃用
  • 在 iOS8 上,我在viewWillTransitionToSize 中调用coordinator.animateAlongsideTransition,并在其animation 块中调用performBatchUpdates。这给出了一个很好的动画效果。
【解决方案2】:

如果你不想performBatchUpdates:completion:带来额外的动画,就用invalidateLayout强制collectionViewLayout重新加载。

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

【讨论】:

    【解决方案3】:

    我使用两个 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];
        }
    }
    

    【讨论】:

      【解决方案4】:

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

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

      不确定它是否可以动画化。

      【讨论】:

      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

        如果您使用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);
            }   
            }     
        }
        

        【讨论】:

        • 这很好用! willRotateToInterfaceOrientation 在 iOS 8 中已弃用,但 viewWillTransitionToSize 也适用于此。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-19
        • 2021-04-18
        • 1970-01-01
        相关资源
        最近更新 更多