设备旋转时如何自动调整 UICollectionView 的大小?

Posted

技术标签:

【中文标题】设备旋转时如何自动调整 UICollectionView 的大小?【英文标题】:How to auto-resize UICollectionView when device rotates? 【发布时间】:2016-12-02 08:21:00 【问题描述】:

每次我旋转设备时,我都在尝试调整我的 collectionViewCells 的大小,但我不知道该怎么做。这是我的问题和我的代码。它在 Swift 3 和 Xcode 8 中。

这是我们加载的第一个屏幕

当我旋转设备单元格时仍然具有相同的宽高

另一方面,如果我在设备旋转(横向)时加载 firstScreen(HomePage),然后我再次将设备旋转到纵向,单元格会溢出,所以我看不到它们的侧面。因为宽度仍然与横向宽度相同。

    // MARK: UICollectionViewDataSource

override func numberOfSections(in collectionView: UICollectionView) -> Int 
    return 1


override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
    return allNews.count


override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as! HomeCollectionViewCell

    // Configure the cell
    cell.imageView.image = allNews[indexPath.row].newsPic
    cell.textView.text = allNews[indexPath.row].newsTitle
    return cell


func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 
    let height = (view.frame.width - 32) * 9 / 16
    return CGSize(width: view.frame.width, height: height + 94)



func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat 
    return 0



// MARK: Orientation Changes ( reload the CollectionLayout )
override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) 


最后我没有在 Main.storyboard 中使用自动布局。这是我在 HomeCollectionViewCell 类中的 setupViews() 方法

    private func setupViews() 
    addSubview(imageView)
    addSubview(textView)
    addSubview(separatorView)
    addSubview(dateView)

    addConstraintsWithFormat(format: "H:|-16-[v0]-16-|", views: imageView)
    addConstraintsWithFormat(format: "V:|-16-[v0]-8-[v1(40)]-2-[v2(20)]-8-|", views: imageView, textView, dateView)

    addConstraintsWithFormat(format: "H:|-16-[v0]-16-|", views: textView)
    addConstraintsWithFormat(format: "H:|-16-[v0]-16-|", views: dateView)

    addConstraintsWithFormat(format: "H:|[v0]|", views: separatorView)
    addConstraintsWithFormat(format: "V:[v0(1)]|", views: separatorView)

问候。

已解决!:我使用了这个方法而不是 override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation)

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) 
    super.viewWillTransition(to: size, with: coordinator)
    collectionView?.collectionViewLayout.invalidateLayout()

【问题讨论】:

您使用的是故事板或笔尖的自动布局吗? 感谢您的解决方案,这对我有用——swift 3 xcode 8.3.1 部署目标 ios 10.0 【参考方案1】:

查看我的解决方案。

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.itemSize = CGSize(width: 100, height: 100)
let controller = UICollectionViewController(collectionViewLayout: layout))

在 iOS8+ 中,该函数不再是 override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation)

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) 
        super.viewWillTransition(to: size, with: coordinator)
        if let layout =  self.collectionView?.collectionViewLayout as? UICollectionViewFlowLayout
            layout.itemSize = CGSize(width: 200, height: 200)
        
    

这对我有用。试试看。

【讨论】:

谢谢我在你的帮助下解决了这个问题。唯一的区别是我没有在 viewWillTransitition 方法中使用特定的 itemSize 宽度/高度大小。因为 invalidateLayout() 方法为我们处理了这些。 @UnalCelik 是的。但有时,大小差异很大,我们必须调整它的大小。【参考方案2】:

您应该使用 self.view.bounds 而不是 self.view.frame,因为当设备旋转的框架在纵向和横向中保持不变时,只会更改绑定。

【讨论】:

【参考方案3】:

因为我在集合视图中有固定的行数,所以我必须在设备旋转时调整单元格大小。我希望这会有所帮助:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) 
    guard let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout else 
        return
    

    if UIInterfaceOrientationIsLandscape(UIApplication.shared.statusBarOrientation) 
        //here you can do the logic for the cell size if phone is in landscape

     else 
        //logic if not landscape
    
    let cellSize =  CGSize(width: (size.width - CGFloat(row ))/CGFloat(row)  , height: 90)
    flowLayout.itemSize = cellSize
    flowLayout.invalidateLayout()

* row 是我的行数,你可以根据自己的情况更改。

【讨论】:

以上是关于设备旋转时如何自动调整 UICollectionView 的大小?的主要内容,如果未能解决你的问题,请参考以下文章

Xcode 自动布局和旋转

UITableView 在旋转时使用自动布局调整大小

如何使用自动布局以编程方式快速设置旋转时 UICollectionView 的宽度

UICollectionView 在旋转时重新排列单元格

iOS_book03 -自动旋转自动调整大小尺寸分类器

可以在旋转时自动调整视图的大小以尽可能大吗?