Одиночный CollectionView с несколькими CollectionViewLayout. Почему макет не работает? - PullRequest
0 голосов
/ 13 ноября 2018

У меня есть Single UICollectionView, и я хочу динамически применить два разных макета.

  1. UICollectionViewFlowLayout: макет с ячейкой одинакового размера и изображением круга.

    var flowLayout: UICollectionViewFlowLayout {
        let flowLayout = UICollectionViewFlowLayout()
    
        flowLayout.itemSize = CGSize(width: UIScreen.main.bounds.width/3, height: 140)
        flowLayout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0)
        flowLayout.scrollDirection = UICollectionViewScrollDirection.vertical
        flowLayout.minimumInteritemSpacing = 0.0
    
        return flowLayout
    }
    
  2. Pintrest Layout: https://www.raywenderlich.com/392-uicollectionview-custom-layout-tutorial-pinterest

Например: когда пользователь нажимает кнопку профиля, FlowLayout будет применен, и появится ячейка с изображением в форме круга. когда пользователь нажмет на кнопку Изображение, будет применен макет pintrest и появится ячейка с изображением в форме прямоугольника с динамической высотой.

enter image description here

изначально CollectionView имеет 1.flowLayout, и он выглядит идеально. Но когда я нажимаю кнопку Picture, макет Pintrest портится с предыдущим макетом, как показано на изображении выше.

Ниже приведен код для изменения макета.

if isGrid {
    let horizontal = flowLayout
    recentCollectionView.setCollectionViewLayout(horizontal, animated: true)
    recentCollectionView.reloadData()
}
else {
    let horizontal = PinterestLayout()
    horizontal.delegate = self
    recentCollectionView.setCollectionViewLayout(horizontal, animated: true)
    recentCollectionView.reloadData()
}

Вид иерархии:

У меня есть основное представление Collection, которое содержит заголовок Container и одну нижнюю ячейку. Ячейка содержит другое представление Collection, к которому я применяю несколько макетов. У меня есть две разные ячейки для каждого макета. Я хочу, чтобы размер нижней ячейки был равен Представление в виде коллекции Размер содержимого, позволяющий пользователю прокручивать весь основной вид коллекции по вертикали.

 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        var cell : UICollectionViewCell!

        switch isGrid {
        case true:
            cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SearchProfileCell", for: indexPath)
            if let annotateCell = cell as? SearchProfileCell {
                annotateCell.photo = photos[indexPath.item]
            }
        case false:
             cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AnnotatedPhotoCell", for: indexPath)

            if let annotateCell = cell as? AnnotatedPhotoCell {
                annotateCell.cellwidth = collectionView.contentSize.width/3
                annotateCell.photo = photos[indexPath.item]

            }
        }

        cell.contentView.layer.cornerRadius = 0
        return cell
    }

Код кнопки профиля и изображения Действие.

@IBAction func pictureClick(sender:UIButton) {
        isGrid = false
        self.searchCollectionView.reloadData()
    }

    @IBAction func profilClick(sender:UIButton) {
        isGrid = true
        self.searchCollectionView.reloadData()
    }

Ответы [ 2 ]

0 голосов
/ 15 ноября 2018

Почему вы используете два разных макета, даже если вы можете достичь того же результата с помощью pintrestLayout.https://www.raywenderlich.com/392-uicollectionview-custom-layout-tutorial-pinterest.

Тщательно проверьте pintrestLayout, у него есть Делегат для Динамической высоты.

 let photoHeight = delegate.collectionView(collectionView, heightForPhotoAtIndexPath: indexPath)

если вы вернете здесь статическую высоту, ваш макет pintrest станет GridLayout (ваш Первый макет).

если вы хотите, чтобы макет pintrest работал как для обоих макетов, вам нужно объявить один и тот же логический (isGrid) в макете pintrest. И использовать этот логический аргумент для возврата UICollectionViewLayoutAttributes

более важный макет raywenderlich использует кеш для хранения макетаattribute.you должен удалить объект кэша перед применением другого макета.

Проверьте в этом руководстве, как этот же макет используется для сетки, списка и линейного.https://benoitpasquier.com/optimise-uicollectionview-swift/

что вам нужно в вашем макете.

 var isGrid : Bool = true {
        didSet {
            if isGrid != oldValue {
                cache.removeAll()
                self.invalidateLayout()
            }
        }
    }
0 голосов
/ 13 ноября 2018

Я думаю, что проблема не в макете, а в cellForItemAt.если вы используете разные ячейки для обоих макетов, не сравнивайте bool в методе cellForItemAt.Вы должны сравнить тип класса макета, как показано ниже:

 func  collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        if collectionView.collectionViewLayout.isKind(of: PinterestLayout.self) {
           // return cell for PinterestLayout 
             guard let annotateCell = collectionView.dequeueReusableCell(withReuseIdentifier: "SearchProfileCell", for: indexPath) as? SearchProfileCell else {
              fatalError("SearchProfileCell Not Found")
            }
            annotateCell.photo = photos[indexPath.item]
            return annotateCell
        } else {
         // return cell for flowLayout 
              guard let annotateCell = collectionView.dequeueReusableCell(withReuseIdentifier: "AnnotatedPhotoCell", for: indexPath) as? AnnotatedPhotoCell else {
                fatalError("AnnotatedPhotoCell Not Found")
             }
             annotateCell.cellwidth = collectionView.contentSize.width/3
             annotateCell.photo = photos[indexPath.item]
             return annotateCell
        }
 }

Также необходимо обновить методы действия изменения макета, такие как:

     @IBAction func pictureClick(sender:UIButton) {
               isGrid = false

        self.collectionView?.collectionViewLayout.invalidateLayout()  
       self.collectionView?.setCollectionViewLayout(PinterestLayout(), 
             animated: false, completion: { [weak self] (complite) in
                    guard let strongSelf = self else {
                        return
                    }
                    strongSelf.searchCollectionView?.reloadData()
                })
       }

      @IBAction func profilClick(sender:UIButton) {
          isGrid = true
          self.collectionView?.collectionViewLayout.invalidateLayout()              
       self.collectionView?.setCollectionViewLayout(flowLayout, 
             animated: false, completion: { [weak self] (complite) in
                    guard let strongSelf = self else {
                        return
                    }
                    strongSelf.searchCollectionView?.reloadData()
                })
     }
...