如何在 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)
}
我有 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)
}