Подкласс iOS13 UICollectionViewFlowLayout не получает изменения коллекции collectionView - PullRequest
0 голосов
/ 09 октября 2019

Я тестирую некоторый код, и похоже, что в iOS13 UICollectionViewFlowLayout не получает изменения в фрейме collectionView.

Ниже приведен пример кода, в котором я просто изменяю высоту на основе collectionView. на сумму, которую я прокручиваю в табличном представлении ниже collectionView:

ViewController

func scrollViewDidScroll(_ scrollView: UIScrollView) {  
    collectionView.collectionViewLayout.invalidateLayout()  

    let totalScroll = scrollView.contentSize.height - scrollView.bounds.size.height  
    let offset = (scrollView.contentOffset.y)  
    let percentage = offset / totalScroll  

    var frame = collectionView.frame  
    frame.size.height = 40 - (40 * percentage)  
    collectionView.frame = frame  
  }

CustomCollectionViewFlowLayout: UICollectionViewFlowLayout

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {  
    let attributes = super.layoutAttributesForElements(in: rect)  
    print(collectionView?.frame)  
    return attributes  
  }  

оператор печати внутри CustomCollectionViewFlowLayout в iOS 12 и нижевыводит изменения в collectionView.frame правильно, т.е. высота фактически изменяется. Но в iOS 13 это никак не отражается.

Помогите кому-нибудь?

1 Ответ

2 голосов
/ 22 октября 2019

Прежде всего,

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    collectionView.collectionViewLayout.invalidateLayout()
    ...
}

выглядит подозрительно. Вы уверены, что ваш макет должен быть признан недействительным внутри функции scrollViewDidScroll?

Существует подходящее место, где макет должен быть недействительным при прокрутке:

final class CustomCollectionViewFlowLayout: UICollectionViewFlowLayout {

    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        // proper place to invalidate layout while scrolling
    }
}

Если вы аннулировали свой макетвнутри класса макета вы сможете правильно рассчитать желаемую высоту контейнера макета. И тогда вы можете сообщить представлению вашей коллекции, что ее высота должна быть изменена. Например, с помощью некоторого делегата:

protocol CustomCollectionViewFlowLayoutSizeDelegate: class {

    func newSizeAvailableFor(layout: CustomCollectionViewFlowLayout, progress: CGFloat)
}

final class CustomCollectionViewFlowLayout: UICollectionViewFlowLayout {

    weak var sizeDelegate: CustomCollectionViewFlowLayoutSizeDelegate?

    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        // proper place to invalidate layout while scrolling
    }
}

final class CustomViewController: CustomCollectionViewFlowLayoutSizeDelegate {

    func newSizeAvailableFor(layout: CustomCollectionViewFlowLayout, progress: CGFloat) {
        // change collectionView frame
    }
}

Вывод:

Ваш макет пытается прослушать высоту своего контейнера, но высота его контейнера рассчитывается на основе вашего макета. Вы можете легко удалить зависимость контейнера для расчета высоты или просто предоставить макету начальную высоту контейнера. В конце концов макет будет отвечать за все расчеты.

...