UIcollectionView не обновляет размер и расположение UIcollectionCell при повороте телефона - PullRequest
0 голосов
/ 20 октября 2019

У меня есть UIcollectionView с изображениями. Когда я поворачиваю экран, ячейки меняются не так, как ожидалось. Я попытался добавить collectionView.collectionViewLayout.invalidateLayout () к viewDidLayoutSubviews () - но это только вызывает сбой. Пожалуйста, кто-то может посоветовать?

У меня есть UIcollectionView с изображениями. Когда я поворачиваю экран, ячейки меняются не так, как ожидалось. Я попытался добавить collectionView.collectionViewLayout.invalidateLayout () к viewDidLayoutSubviews () - но это только вызывает сбой. Кто-нибудь может посоветовать?

Портрет:

enter image description here

Landdscape:

enter image description here

class GridPicksCollectionViewController: UICollectionViewController{

let cellId = "gridyPickCell"
var numCelPerRow: CGFloat = 3
var layout: UICollectionViewFlowLayout!
let borderInset: CGFloat = 3
let interCellSpacing: CGFloat = 3
let spacingBetweenRows: CGFloat = 3
var dataSource = [UIImage]()
var collectionViewWidth: CGFloat!


override func viewDidLoad() {
    super.viewDidLoad()

    generalSetup()
    setUpDateSource()
    setupCollectionViewLayout()
}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    print("viewDidLayoutSubviews")

    // Update collectionViewWidth upon rotation
    collectionViewWidth = self.collectionView.frame.width
    //collectionView.collectionViewLayout.invalidateLayout() - causes app to crash

}

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    print("viewWillTransition")
}


private func generalSetup(){
    navigationController?.navigationBar.barTintColor = UIColor.appDarkGreen
    navigationItem.title = "Girdy Picks"
    let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
    navigationController?.navigationBar.titleTextAttributes = textAttributes
    collectionView.backgroundColor = UIColor.white
    collectionViewWidth = collectionView.frame.width

    // Make sure collectionView is always within the safe area layout
    if #available(iOS 11.0, *) {
        collectionView?.contentInsetAdjustmentBehavior = .always
    }

    // Register UICollectionViewCell
    collectionView.register(GirdyPickCollectionCell.self, forCellWithReuseIdentifier: cellId)
}


private func setUpDateSource(){
    let images: [UIImage] = [UIImage.init(named: "buddha")!, UIImage.init(named: "sharpener")!,  UIImage.init(named: "cars")!, UIImage.init(named: "houses")!, UIImage.init(named: "houses2")!, UIImage.init(named: "tower1")!, UIImage.init(named: "tower2")!]
    dataSource = images

}

private func setupCollectionViewLayout(){
    collectionView.delegate = self
    collectionView.dataSource = self
    layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout
    layout.minimumInteritemSpacing = interCellSpacing // distance between cells in a row
    layout.minimumLineSpacing = spacingBetweenRows // distance in between rows
    layout.sectionInset = UIEdgeInsets.init(top: borderInset, left: borderInset, bottom: borderInset, right: borderInset) // border inset for collectionView
}
}


extension GridPicksCollectionViewController: UICollectionViewDelegateFlowLayout{

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

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! GirdyPickCollectionCell
    cell.imageView.image = dataSource[indexPath.row]
    return cell
}

override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let selectedImage = dataSource[indexPath.row]
    let showImageVC = ImageGridViewController()
    showImageVC.modalPresentationStyle = .fullScreen
    showImageVC.imageToDisplay = selectedImage
    self.present(showImageVC, animated: true) {}
}


// Determine size for UICollectionCell
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    print("sizeForItemAt")
    guard let collectionWidth = collectionViewWidth else{ return CGSize.init()}
    let widthCell = (collectionWidth - interCellSpacing * 2 - borderInset * 2) / numCelPerRow
    return CGSize.init(width: widthCell, height: widthCell)
}
}

1 Ответ

0 голосов
/ 21 октября 2019

Вы ошибаетесь в своем жизненном цикле событий. Когда устройство поворачивается, ваша иерархия представлений получает уведомление об этом событии, и представления начинают перестраивать себя, основываясь на имеющейся у них информации. После того, как это было закончено, будет вызываться viewDidLayoutSubviews(), а не раньше.

Поскольку вы обновляете свойство collectionViewWidth в этом методе, макет все еще использует старое значение при вызовеcollectionView(_:layout:sizeForItemAt:). Вам нужно установить это значение в viewWillLayoutSubviews().

В качестве альтернативы, вы можете написать установщик для этого свойства, который будет вызывать invalidateLayout() в макете представления коллекции, но это вызовет ненужный проход макета.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...