代码之家  ›  专栏  ›  技术社区  ›  Jordan H

更改流布局的itemSize后单元格大小未更新

  •  9
  • Jordan H  · 技术社区  · 7 年前

    在我的应用程序中,我有一个全屏分页集合视图,每个单元格也需要全屏,因此集合视图布局的项目大小需要与视图控制器视图的边界大小相同。为此,在 viewDidLayoutSubviews 我只是简单地设置项目大小,它是按预期工作。当我呈现这个屏幕时, viewDidLayoutSubviews 调用3次,每次iPhone 7的视图边界大小为375.0 x 667.0。单元格大小与预期相同。

    但是,当使用3D Touch peek and pop呈现此屏幕时,单元格的大小与预期不符,无论是在偷看还是弹出时。 调用4次,边界大小如下:

    --- peek triggered ---
    375.0 x 569.524495677234
    375.0 x 569.524495677234
    375.0 x 720.821325648415
    --- pop triggered ---
    375.0 x 667.0
    

    偷看时,收集视图如预期的那样是“全屏”的,高度为721,单元格的预期宽度为375,但单元格高度为569,而它本应为721。弹出时,收集视图高度如预期的那样更改为667,但单元格高度仍为569。

    collectionView.layoutIfNeeded() 设置后 itemSize

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
    
        print("\(view.bounds.width) x \(view.bounds.height)")
    
        let boundsSize = CGSize(width: Int(view.bounds.width), height: Int(view.bounds.height))
        let flowLayout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
    
        if flowLayout.itemSize != boundsSize {
            flowLayout.itemSize = boundsSize
    
            collectionView.layoutIfNeeded() //this doens't help
        }
    }
    
    5 回复  |  直到 6 年前
        1
  •  19
  •   iqra    4 年前

    将集合视图的“估计大小”从检查器更改为“无”! 以上所有答案都不适用于我。

    Estimate Size

        2
  •  16
  •   Chen Jiling    6 年前

    这似乎是UICollectionViewFlowLayout的一个bug, 我必须在invalidateLayout()之前调用prepare()

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
    
    
        guard let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else
        {
            return
        }
    
        layout.itemSize = cellSize
        layout.minimumLineSpacing = space
        layout.prepare()  // <-- call prepare before invalidateLayout
        layout.invalidateLayout()
    }
    
        3
  •  1
  •   Zoe - Save the data dump RobG    6 年前

    尝试替换 collectionView.layoutIfNeeded() flowLayout.invalidateLayout()

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
    
        print("\(view.bounds.width) x \(view.bounds.height)")
    
        let boundsSize = CGSize(width: Int(view.bounds.width), height: Int(view.bounds.height))
        let flowLayout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
    
        if flowLayout.itemSize != boundsSize {
            flowLayout.itemSize = boundsSize
    
            debugPrint("Called")
            flowLayout.invalidateLayout()
        }
    }
    
        4
  •  0
  •   Puneet Sharma    7 年前

    您可以使用 collectionView(_:layout:sizeForItemAt:) 随着 viewDidLayoutSubviews .

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
    
        print("\(view.bounds.width) x \(view.bounds.height)")
    
        let boundsSize = CGSize(width: Int(view.bounds.width), height: Int(view.bounds.height))
    
        if !boundsSize.equalTo(self. collectionViewItemSize) {
            collectionView.invalidateLayout()
        }
    }
    
    var collectionViewItemSize:CGSize = .zero
    
    func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAt indexPath: IndexPath) -> CGSize {
        self.collectionViewItemSize = CGSize(width: Int(view.bounds.width), height: Int(view.bounds.height));
        return self.collectiViewItemSize;
    }
    
        5
  •  0
  •   Yariv Nissim    6 年前

    我最终改变了 itemSize viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) 并将大小传递给一个方法,该方法将根据视图的未来大小进行计算。