如何在 swift 中制作可扩展的 collection 视图?

how to make expandable collection view in swift?

我有 2 个 collection 视图部分,当这个 VC 第一次加载时,两个部分(室内和室外)最初只会显示 3 个项目。

但在用户按下"More"按钮后,室内或室外的每个部分都会展开并显示所有可用项目,如下图

我试过编代码,但是好像有时能展开有时不能展开(还是显示3项)。

这是主控制器中的代码:

class FacilitiesVC: UIViewController {

    @IBOutlet weak var collectionView: UICollectionView!

    var facilitiesCategoryData = [[String:Any]]()
    var outdoorFacilitiesIsExpanded = false
    var indoorFacilitiesIsExpanded = false

    override func viewDidLoad() {
        super.viewDidLoad()

        getIndoorOutdoorFacilitiesData()
    }

}

extension FacilitiesVC {

    // MARK: - Helper Methods

    func getIndoorOutdoorFacilitiesData() {

        let facilitiesData = FacilitiesCategoryLibrary.fetchFacilitiesCategory()
        var indoorFacilities = [FacilitiesCategory]()
        var outdoorFacilities = [FacilitiesCategory]()

        // distinguishing between indoor and outdoor data
        for facData in facilitiesData {

            if facData.type == "Indoor Facility" {
                indoorFacilities.append(facData)
            } else {
                outdoorFacilities.append(facData)
            }
        }

        facilitiesCategoryData = [
            ["title": "Indoor Facilities", "info": indoorFacilities],
            ["title": "Outdoor Facilities", "info": outdoorFacilities]
        ]
    }

}

extension FacilitiesVC: UICollectionViewDataSource {

    // MARK: - UICollectionViewDataSource

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return facilitiesCategoryData.count
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

        if section == 0 {

            if indoorFacilitiesIsExpanded {
                let category = facilitiesCategoryData[section]
                let infoList = category["info"] as! [FacilitiesCategory]
                return infoList.count
            } else {
                return 3
            }

        } else {

            if outdoorFacilitiesIsExpanded {
                let category = facilitiesCategoryData[section]
                let infoList = category["info"] as! [FacilitiesCategory]
                return infoList.count
            } else {
                return 3
            }

        }
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: StoryBoard.facilitiesCategoryCellIdentifier, for: indexPath) as! FacilitiesCell

        let category = facilitiesCategoryData[indexPath.section]
        let infoList = category["info"] as! [FacilitiesCategory]
        cell.facilitiesCategoryData = infoList[indexPath.item]

        return cell
    }

    // for section header view
    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

        let sectionHeaderView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: StoryBoard.facilitiesSectionHeaderIdentifier, for: indexPath) as! FacilitiesSectionHeader

        let category = facilitiesCategoryData[indexPath.section]
        sectionHeaderView.categoryData = category
        sectionHeaderView.sectionHeaderDelegate = self

        return sectionHeaderView
    }

}

extension FacilitiesVC: FacilitiesSectionHeaderDelegate {

    func didPressButton(_ facilities: String, isExpanded: Bool) {

        if facilities == "Indoor Facilities" {
            indoorFacilitiesIsExpanded = isExpanded
        } else if facilities == "Outdoor Facilities" {
            outdoorFacilitiesIsExpanded = isExpanded
        }

        collectionView.reloadData()
    }

}

这里是 collection 视图部分中的代码 header

import UIKit

protocol FacilitiesSectionHeaderDelegate: class {
    func didPressButton(_ facilities: String, isExpanded: Bool)
}

class FacilitiesSectionHeader: UICollectionReusableView {

    @IBOutlet weak var titleLabel: UILabel!

    weak var sectionHeaderDelegate: FacilitiesSectionHeaderDelegate?

    var collectionIsExpanded = false
    var facilitiesType = ""

    var categoryData: [String:Any]! {
        didSet {
            titleLabel.text = categoryData["title"] as? String
            facilitiesType = categoryData["title"] as! String
        }
    }

    @IBAction func moreButtonDidPressed(_ sender: Any) {
        collectionIsExpanded = !collectionIsExpanded
        sectionHeaderDelegate?.didPressButton(facilitiesType, isExpanded: collectionIsExpanded)
    }

}

可能是我在collection numberOfItemsInSection这行代码中出错了

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

    if section == 0 {

        if indoorFacilitiesIsExpanded {
            let category = facilitiesCategoryData[section]
            let infoList = category["info"] as! [FacilitiesCategory]
            return infoList.count
        } else {
            return 3
        }

    } else {

        if outdoorFacilitiesIsExpanded {
            let category = facilitiesCategoryData[section]
            let infoList = category["info"] as! [FacilitiesCategory]
            return infoList.count
        } else {
            return 3
        }

    }
}

我认为 section argument 参数与 indexPath.section 相同,但似乎不同,但我不知道如何从 [=43= 访问 indexPath.section ] numberOfItemsInSection方法

如何解决?

您必须在 viewForSupplementaryElementOfKind

中分配当前状态
 func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

    let sectionHeaderView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: StoryBoard.facilitiesSectionHeaderIdentifier, for: indexPath) as! FacilitiesSectionHeader

    let category = facilitiesCategoryData[indexPath.section]
    sectionHeaderView.categoryData = category
    sectionHeaderView.sectionHeaderDelegate = self

    if(indexPath.section == 0)
    {
       sectionHeaderView.collectionIsExpanded =  indoorFacilitiesIsExpanded
    }
    else
    {
      sectionHeaderView.collectionIsExpanded = outdoorFacilitiesIsExpanded
    }

    return sectionHeaderView
}

如里面FacilitiesSectionHeader你照着翻

 @IBAction func moreButtonDidPressed(_ sender: Any) {

    collectionIsExpanded = !collectionIsExpanded
    sectionHeaderDelegate?.didPressButton(facilitiesType, isExpanded: collectionIsExpanded)

}