【问题标题】:UICollectionViewCell resizing on device rotationUICollectionViewCell 在设备旋转时调整大小
【发布时间】:2017-03-19 08:11:20
【问题描述】:

我在 ViewController 中嵌入了一个非常简单的 UICollectionView。

UICollectionView 使用自动布局(在 IB 中定义)占据 ViewController 中的整个空间。

我的 UICollectionViewCell 的大小都相同,它们占据了 UICollectionView 的整个空间,因为我希望在 ViewController 中只显示一个单元格。 UICollectionViewCell 只显示一个 UIImage(它嵌入在 UIScrollView 中用于缩放)。

它工作正常,除非设备旋转。有一个错误信息:

未定义 UICollectionViewFlowLayout 的行为,因为: 项目高度必须小于 UICollectionView 的高度减去部分插入顶部和底部值,减去内容插入顶部和底部值。 相关的 UICollectionViewFlowLayout 实例是 ,它附加到 ;动画 = { bounds.origin=; bounds.size=;位置=; };层 = ;内容偏移:{0, 0}; contentSize: {4875, 323}> 集合视图布局:。

很清楚,我需要调整 UICollectionViewCell 的大小以适应新的高度/宽度。旋转后,UICollectionViewCell 以适当的高度/宽度显示,但动画效果不佳。

代码如下:

@IBOutlet weak var theCollectionView: UICollectionView!
@IBOutlet weak var theFlowLayout: UICollectionViewFlowLayout!
    override func viewDidLoad() {
    super.viewDidLoad()

    //theCollectionView.delegate = self
    theCollectionView.dataSource = self
    automaticallyAdjustsScrollViewInsets = false
    theFlowLayout.itemSize = theCollectionView.frame.size
    theFlowLayout.sectionInset = UIEdgeInsetsMake(0,0,0,0)
    theFlowLayout.minimumLineSpacing = 0.0
    theCollectionView.reloadData()
}


override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
}

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    print("\(#function) \(view.frame.size)")
    coordinator.animate(alongsideTransition: nil, completion: {
        _ in
        self.theFlowLayout.itemSize = self.theCollectionView.frame.size
    })        
}

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    print("\(#function) \(view.frame.size)")
}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    print("\(#function) \(view.frame.size)")
}

问题是,如何以及何时执行 UICollectionViewCell 更改以避免警告并获得流畅的动画?

当设备旋转发生时,我可以看到以下内容: viewWillTransition(to:with:) (375.0, 667.0) viewWillLayoutSubviews() (667.0, 375.0) viewDidLayoutSubviews() (667.0, 375.0)

错误显示在 viewDidLayoutSubviews() 之后。我试图在 viewDidLayoutSubviews() 中调用 theFlowLayout.invalidateLayout() 但它并没有改变问题。

我已经阅读了其他类似的问题,但我找不到我的答案:-(

感谢您的帮助,

塞巴斯蒂安

【问题讨论】:

    标签: ios rotation uicollectionview uicollectionviewcell


    【解决方案1】:

    我还没有找到最好的解决方案,但至少它有效。

    我使用 viewWillTransition 来计算单元格的索引并在旋转后重置偏移量。为避免动画效果不佳,我在开始时将 alpha 设置为 0,在动画结束时再次设置为 1。

    viewWillLayoutSubviews 用于使 UICollectionViewFlowLayout 和 viewDidLayoutSubviews 的布局失效以设置新的单元格大小。

    也许会对其他人有所帮助,但如果您有更好的解决方案,请分享!

        @IBOutlet weak var theCollectionView: UICollectionView! {
        didSet {
            theCollectionView.backgroundColor = UIColor.black
            theCollectionView.delegate = self
            theCollectionView.dataSource = self
        }
    }
    
    @IBOutlet weak var theFlowLayout: UICollectionViewFlowLayout! {
        didSet {
            theFlowLayout.itemSize = theCollectionView.frame.size
            theFlowLayout.sectionInset = UIEdgeInsetsMake(0,0,0,0)
            theFlowLayout.minimumLineSpacing = 0.0
        }
    }
    
    var assets:[PHAsset]!
    var startAssetIndex = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.black
        automaticallyAdjustsScrollViewInsets = false
        theCollectionView.reloadData()
    }
    
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        theCollectionView.scrollToItem(at: IndexPath(row:startAssetIndex, section:0), at: .left, animated: true)
    }
    
    
    /// Resize the collectionView during device rotation
    ///
    /// - Parameters:
    ///   - size: New size of the viewController
    ///   - coordinator: coordinator for the animation
    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
    
        // Compute the index of the image/video currently displayed
        let offset = self.theCollectionView.contentOffset;
        let index = round(offset.x / self.theCollectionView.bounds.size.width);
    
        // hide the collection view to avoid horrible animation during the rotation
        // animation is horrible due to the offset change
        theCollectionView.alpha = 0.0
        coordinator.animate(alongsideTransition: nil, completion: {
            _ in
            // display the collectionView during the animation
            self.theCollectionView.alpha = 1.0
    
            // compute the new offset based on the index and the new size
            let newOffset = CGPoint(x: index * self.theCollectionView.frame.size.width, y: offset.y)
            self.theCollectionView.setContentOffset(newOffset, animated: false)
        })
    }
    
    
    /// Invalidate the layout of the FlowLayout, it's mandatory for the rotation
    override func viewWillLayoutSubviews() {
        theFlowLayout.invalidateLayout()
        super.viewWillLayoutSubviews()
    }
    
    
    /// Set the size of the items (mandatory for the rotation)
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        theFlowLayout.itemSize = theCollectionView.frame.size
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-02
      • 2018-11-11
      • 2011-12-29
      • 2012-01-06
      • 1970-01-01
      • 1970-01-01
      • 2016-03-12
      • 1970-01-01
      相关资源
      最近更新 更多