UICollectionViewCell在设备轮换时调整大小

时间:2016-11-05 16:24:38

标签: ios rotation uicollectionview uicollectionviewcell

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

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

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

除非设备旋转,否则工作正常。有一条错误消息:

  

未定义UICollectionViewFlowLayout的行为,因为:   项高度必须小于UICollectionView的高度减去截面插入顶部和底部值,减去内容插入顶部和底部值。   相关的UICollectionViewFlowLayout实例是,并附加到;动画= {bounds.origin =; bounds.size =;位置=; }; layer =; contentOffset:{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()中调用FlowLayout.invalidateLayout(),但它不会改变问题。

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

感谢您的帮助,

的Sebastien

1 个答案:

答案 0 :(得分: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
}