【问题标题】:UICollectionViewCell layout issues iOS9UICollectionViewCell 布局问题 iOS9
【发布时间】:2015-12-14 08:46:18
【问题描述】:

自从我迁移到新的 iOS9 和 Xcode 7 后,我偶然发现了我的应用程序中 UICollectionView 之一的问题。

显然,UICollectionView 似乎没有正确更新 UICollectionViewCell 布局和约束,直到它被重用。

图片胜于雄辩——这是UIViewController第一次出现时的样子:

但这不是正确的布局,当我将UICollectionView 水平向左滑动时,我很容易得到新出现的单元格的正确布局:

当我向后滑动时,不正确的旧单元格现在可以重复使用并且看起来不错。

现在,就像在升级到 iOS9 和 Xcode 7 之前一样,我想要的效果是单元格即使在第一次出现时也具有正确的布局。

为方便起见,以下是有关如何设置 UICollectionView 及其在 XIB 中的约束的更多详细信息:

在代码中,很标准:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell : MatchmakersCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionCell", forIndexPath: indexPath) as! MatchmakersCollectionViewCell

    cell.imageView.backgroundColor = UIColor.lightGrayColor()
    cell.bottomName.text = "StackOverflow"

    return cell
}

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return self.matchmakers.count
}

func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
    return 1
}

而且每次我更新数据源(self.matchmakers)时,我都会打电话给self.collectionView.reloadData()

我注意到的最后一件事很奇怪,当使用 Xcode 调试调试视图层次结构时,UICollectionViewCell 从未正确显示子视图,只是给了我一个默认的 UIView 代替它们:

【问题讨论】:

    标签: ios uicollectionview uicollectionviewcell ios9 xcode7


    【解决方案1】:

    解决这个问题:

    1. 使用 Nib(.xib) 文件创建您的自定义 UICollectionViewCell。

    2. 在您的自定义 UICollectionViewCell 中,覆盖 didMoveToSuperView() 方法以添加此

      self.setNeedLayout()

      self.layoutIfNeeded()

    3.在你的 UIViewController viewDidLoad() 方法中

    self.collectionView.registerNib(UINib(nibName: "yourNibName", bundle: nil), forCellWithReuseIdentifier: "Cell")

    --------更新20150923

    只需要第2步,重写didMoveToSuperView方法添加

    self.setNeedLayout()

    self.layoutIfNeeded()

    在您的自定义 UICollectionViewCell 类中。

    谢谢@macayer

    【讨论】:

    • 在自定义项目类中的- (void)didMoveToSuperview 中调用setNeedsLayoutlayoutIfNeeded 方法在iOS 9.0 公开版本中对我有用。我想知道这在效率方面如何...... viewDidLoad 部分和单独的 Nib 文件不是必需的。
    • 步骤 1 和 3 不是必需的。第 2 步正是您所需要的。
    【解决方案2】:

    我不必为我的单元创建自己的 XIB,只要我有我的自定义单元并将其链接到我的故事板,我只需在 (MyCustomCollectionViewCell.m) 中添加这些行:

    - (void)didMoveToSuperview{
        [super didMoveToSuperview];
    
        [self setNeedsLayout];
        [self layoutIfNeeded];
    }
    

    【讨论】:

      【解决方案3】:

      我在 iOS9 中也有同样的错误。也许你发现在你重新加载集合视图后一切正常。所以我的解决方案:为 iOS9 设置一个计时器来重新加载单元格。

      if #available(iOS 9, *) {
         self.refreshTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("refreshDataTimer"), userInfo: nil, repeats: true)
      }
      

      然后重新加载它们:

      func refreshDataTimer(){
      
          self.collectionView?.reloadData()
      
      }
      

      尽管这个解决方案有点愚蠢,但它只需要几行代码。

      或者您可以重新加载每个单元格:

      func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
      
           .... 
      
      
          self.collectionView?.reloadItemsAtIndexPaths([indexPath])
          return cell
      }
      

      但是效率低下。

      【讨论】:

      • 为什么这个解决方案会起作用,因为 reloadItemsAtIndexPaths 方法会调用 cellForRowAtcellForRowAt 然后它会再次执行方法 reloadItemsAtIndexPaths 所以我想知道为什么这个解决方案可以工作??
      • 有点讨厌...最好的情况是 UI 出现不必要的延迟,最坏的情况是 Timer 假定视图已完成加载(可能仍然会发生)。
      【解决方案4】:

      我在 iOS9 中遇到了同样的错误。我想要 UICollectionView 单元的中心 x 和中心 y 图像。它不起作用,但现在我添加了故事板Align TopAlign Leading,然后我添加了出口NSLayoutConstraint

      (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath。我正在根据分辨率更改NSLayoutConstraint

      【讨论】:

        【解决方案5】:

        我很肯定这是一个 iOS9 错误。我没有在 Storyboard 的 UICollectionView 中设置 UICollectionViewCell UI 和约束,而是创建了它自己的 XIB。然后添加到UIViewController

        self.collectionView.registerNib(UINib(nibName: "MatchmakersCollectionViewCell", bundle: NSBundle.mainBundle()), forCellWithReuseIdentifier: "CollectionCell")
        

        现在效果很好。

        【讨论】:

          【解决方案6】:

          我遇到了 OP 描述的问题的一部分...

          调试时我注意到的最后一件事很奇怪 使用 Xcode 调试视图层次结构,UICollectionViewCell 永远不会 正确展示了子视图,只是给了我一个默认的 UIView 他们的替代品

          我花了很长时间将头撞在墙上试图弄清楚发生了什么,但建议的答案都没有产生任何影响。最后,我最终删除了我的单元格 XIB 中的所有约束并重新添加它们,它解决了问题。我猜这些约束在某些时候一定已经损坏了。

          希望它可以帮助某人。

          【讨论】:

            【解决方案7】:

            在我的例子中,禁用 .xib 文件中的大小类就可以了。

            【讨论】:

              【解决方案8】:

              这是在 Xcode 7 中解决此问题所需的相应 Swift 2.0 代码。请注意,正确的代码是“setNeedsLayout”而不是“SetNeedLayout”,如上所述。确保在 UICollectionViewCell 文件中调用它。

               override func didMoveToSuperview() {
                          self.setNeedsLayout()
                          self.layoutIfNeeded()
                      }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2017-11-01
                • 1970-01-01
                • 2018-10-28
                • 1970-01-01
                相关资源
                最近更新 更多