Сохраняйте перекрытие ячеек вида коллекции при их перерисовке

#ios #swift #uicollectionview #uicollectionviewcell #uicollectionviewlayout

#iOS #swift #uicollectionview #uicollectionviewcell #uicollectionviewlayout

Вопрос:

Я заставил свои ячейки перекрываться, установив для minimumLineSpacing свойства макета представлений коллекции значение negative. Но, когда я прокручиваю и ячейки перерисовываются, они теперь перекрываются в противоположном направлении. Я поместил картинки ниже.

введите описание изображения здесь введите описание изображения здесь

Как мне сохранить перекрытие ячеек, как показано на первом рисунке, когда вид коллекции прокручивается, а ячейки перерисовываются?

 import UIKit

class PopularView: UIView {

let cellID = "cellID"

// MARK: - Views
let collectionView: UICollectionView = {
    let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .vertical
    layout.minimumLineSpacing = -55     // -------Allows Overlap-----
    layout.itemSize = CGSize(width: SCREEN_WIDTH, height: 185)
    layout.minimumInteritemSpacing = 17
    let view = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
    view.backgroundColor = .white
    return view
}()



// MARK: - Initializers
override init(frame: CGRect) {
    super.init(frame: frame)
    collectionView.dataSource = self
    collectionView.register(PopularCell.self, forCellWithReuseIdentifier: cellID)

    backgroundColor = .white
    setupCollectionView()
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}



// MARK: - Setup
fileprivate func setupCollectionView() {
    self.addSubview(collectionView)
    collectionView.anchors(top: self.topAnchor, topPad: 0, bottom: self.bottomAnchor, bottomPad: 0, left: self.leftAnchor, leftPad: 0, right: self.rightAnchor, rightPad: 0, height: nil, width: nil)
    collectionView.contentSize = CGSize(width: 700, height: 700)
    }
}

extension PopularView: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 500
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellID, for: indexPath) as! PopularCell
    cell.background.backgroundColor = .random
    return cell
    }
}
  

Комментарии:

1. Подклассируйте UICollectionViewLayout и используйте пользовательские атрибуты макета для каждого элемента. Минимальный интервал может не помочь.

2. Какие конкретные атрибуты я должен редактировать при создании подкласса UICollectionViewLayout ?

3. Взгляните на эту ссылку и посмотрите, соответствует ли она вашим требованиям.

4. Определенно полезно, но у меня все еще возникают проблемы с пониманием того, как работает подкласс свойства layout, и как это сделать правильно.

Ответ №1:

Попробуйте это, это может вам помочь:

1- Внутри ваших ячеек вы можете определить innerView внутри вашей ячейки и установить рамку в

 let innerView:UIView = CGRect(x: 0,y: -overlapHeight,width: screenWidth, height:cell.height   overlapHeight)
cell?.contentView.addSubview(innerView)
  

2- Настройте свою ячейку во время инициализации с помощью этого:

 cell?.contentView.clipsToBounds = false
  

3- При загрузке ячейки установите z-порядок:

 override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
        cell.layer.zPosition = CGFloat(indexPath.row)
// configure your cell after here
}
  

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

Я набросал пример кода, который выглядит не идеально, но поможет вам начать:

 private let reuseIdentifier = "Cell"
private let overlapHeight:CGFloat = 100
class CustomCollectionCell:UICollectionViewCell {
    var innerView:UIView?
    override init(frame: CGRect) {
        super.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 300))
        self.backgroundColor = .darkGray
        let innerView = UIView(frame: CGRect(x: 0,y: -overlapHeight,width: UIScreen.main.bounds.width,height: overlapHeight   self.contentView.frame.height))
        self.innerView = innerView
        innerView.layer.cornerRadius = 20
        self.contentView.addSubview(innerView)
        self.contentView.clipsToBounds = false
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func configure(color:UIColor?) {
        innerView?.backgroundColor = color
    }
}

import UIKit

private let reuseIdentifier = "Cell"
private let overlapHeight:CGFloat = 100
class CustomCollectionCell:UICollectionViewCell {
    var innerView:UIView?
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.backgroundColor = .darkGray
        let innerView = UIView(frame: CGRect(x: 0,y: -overlapHeight,width: UIScreen.main.bounds.width,height: overlapHeight   self.contentView.frame.height))
        self.innerView = innerView
        innerView.layer.cornerRadius = 20
        self.contentView.addSubview(innerView)
        self.contentView.clipsToBounds = false
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func configure(color:UIColor?) {
        innerView?.backgroundColor = color
    }
}

class CollectionViewController: UICollectionViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let flowLayout = UICollectionViewFlowLayout()
        flowLayout.itemSize = CGSize(width: UIScreen.main.bounds.width, height: 190)
        flowLayout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
        flowLayout.scrollDirection = .vertical
        flowLayout.minimumInteritemSpacing = 0.0
        collectionView.collectionViewLayout = flowLayout


        // Register cell classes
        self.collectionView!.register(CustomCollectionCell.self, forCellWithReuseIdentifier: reuseIdentifier)


    }

    // MARK: UICollectionViewDataSource

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }


    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of items
        return 30
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
        cell.layer.zPosition = CGFloat(indexPath.row)

        var color:UIColor?
        switch indexPath.row % 4 {
        case 0:
            color = .purple
        case 1:
            color = .yellow
        case 2:
            color = .green
        default:
            color = .red
        }
        if let cell = cell as? CustomCollectionCell {
            cell.configure(color: color)
        }


        return cell
    }



}
  

Результат:

введите описание изображения здесь

Комментарии:

1. Где я могу получить доступ к этому innerView свойству? Кажется, я не могу найти, как получить к нему доступ с помощью моего UICollectionViewCell подкласса.

2. innerView — это представление, которое вы можете определить как первенец вашей ячейки CollectionViewCell.

3. О, я понимаю. К сожалению, это не устранило проблему.

4. Хм, похоже, что-то не так в вашем коде

5. Что, по вашему мнению, нужно изменить?