Reputation: 25
Some of my CollectionView sections should only allow users to select single options, and others should allow users to pick any amount in that section. How can I design a CollectionView such that some sections allow multiple selection and others only allow single selection?
I'm building a food delivery app that asks users to select from a screen of choices to customize their order (i.e. picking sugar level or choosing a side drink). I currently have the list of customizable options displayed as one UICollectionView with different sections specifying what exactly they'd like to customize. To clarify, a section header might say "Choose your Drink" and the cells in this section would list out "Coke," "Pepsi," etc.
class MenuDetailVC: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
var item: MenuItem?
var cvCellID = "collectionviewid"
var masterCustomizables: [MasterCustomize]?
override func viewDidLoad() {
super.viewDidLoad()
masterCustomizables = item?.customizables
setupCV()
}
//...
func setupCV() {
masterCollectionView.dataSource = self
masterCollectionView.delegate = self
masterCollectionView.register(CustomizeCellHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "headerID")
masterCollectionView.register(CustomizeCell.self, forCellWithReuseIdentifier: cvCellID)
masterCollectionView.backgroundColor = UIColor.white
masterCollectionView.allowsMultipleSelection = true
}
}
extension MenuDetailVC {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cvCellID, for: indexPath) as! CustomizeCell
cell.customizable = masterCustomizables?[indexPath.section].choices?[indexPath.row]
return cell
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
if let count = masterCustomizables?.count {
return count
} else {
return 0
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if let count = masterCustomizables?[section].choices?.count {
return count
} else {
return 0
}
}
The class MasterCustomize has an instance variable .isRequired that returns a bool, and if .isRequired == true, the section should contain single selection cells. Otherwise, it should contain multiple selection cells. Obviously, the current state of the program only returns multiple selection cells. Thank you!
Upvotes: 1
Views: 1281
Reputation: 15758
In collectionView shouldSelectItemAt
method check .isRequired
value. If it is true check number of selected cells in that section. If existing selected cells count is 0, return true.
If .isRequired
value is false
, return true
func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
if (masterCustomizables ?? [])[indexPath.section].isRequired {
return collectionView.indexPathsForSelectedItems?.filter { $0.section == indexPath.section }.count == 0
} else {
return true
}
}
Update
If isRequired
is true, deselect already selected cell programmatically.
func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
if (masterCustomizables ?? [])[indexPath.section].isRequired,
let existingSelectedIndex = collectionView.indexPathsForSelectedItems?.first(where: { $0.section == indexPath.section }) {
collectionView.deselectItem(at: existingSelectedIndex, animated: true)
}
return true
}
Upvotes: 3