我有一个按钮,可以选择集合视图中的所有单元格。单击后,按钮功能会发生变化,以便在再次按下时取消选中所有单元格。
到目前为止很好......但是 1)当您使用按钮选择所有单元格时,向下滚动一点并再次向上滚动 2)然后用按钮取消选择所有单元格,再次用按钮选择所有单元格 3)然后开始向下滚动,一些单元格(大多数1-2个完整行,后面的单元格再次正常)未正确更新,因此它们不出现在所选状态,即不同的背景颜色。看起来像dequeueReusableCell的问题,但我无法绕过它...
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
if cell.isSelected {
cell.backgroundColor = UIColor.green
} else {
cell.backgroundColor = UIColor.white
}
if cell.viewWithTag(1) != nil {
let cellTitle = cell.viewWithTag(1) as! UILabel
cellTitle.text = String(indexPath.row)
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if let cell = collectionView.cellForItem(at: indexPath) {
cell.backgroundColor = UIColor.green
selectedCells.append(indexPath.row)
}
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
if let cell = collectionView.cellForItem(at: indexPath) {
cell.backgroundColor = UIColor.white
selectedCells.removeObject(indexPath.row)
}
}
处理按钮点击的操作方法
@IBAction func selectButtonTapped(_ sender: Any) {
if isSelectAllActive {
// Deselect all cells
selectedCells.removeAll()
for indexPath: IndexPath in collectionView!.indexPathsForSelectedItems! {
collectionView!.deselectItem(at: indexPath, animated: false)
collectionView(collectionView!, didDeselectItemAt: indexPath)
let cell: UICollectionViewCell
cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CVCell", for: indexPath)
}
selectButton.title = "Select all"
isSelectAllActive = false
} else {
// Select all cells
for i in 0 ..< collectionView!.numberOfItems(inSection: 0) {
collectionView!.selectItem(at: IndexPath(item: i, section: 0), animated: false, scrollPosition: UICollectionViewScrollPosition())
collectionView(collectionView!, didSelectItemAt: IndexPath(item: i, section: 0))
}
selectedCells.removeAll()
let indexPaths: [IndexPath] = collectionView.indexPathsForSelectedItems!
for item in indexPaths {
selectedCells.append(item.row)
}
selectedCells.sort{$0 < $1}
selectButton.title = "Select none"
isSelectAllActive = true
}
}
完成删除对象的数组扩展
extension Array where Element : Equatable {
mutating func removeObject(_ object : Iterator.Element) {
if let index = self.index(of: object) {
self.remove(at: index)
}
}
}
完整的Xcode项目可以在这里找到:https://www.dropbox.com/s/uaj1asg43z7bl2a/SelectAllCells.zip
使用Xcode 9.0 beta 1,iOS11 Simulator / iPhone SE
感谢您的帮助!
答案 0 :(得分:0)
您的代码有点混乱,因为您试图在数组和单元格本身中跟踪单元格选择状态。
我只使用Set<IndexPath>
因为它比数组更简单,更有效。然后,您可以在cellForItemAt:
中返回单元格时引用此集,并且您不需要在willDisplay
中执行任何操作。
当您选择/取消选择全部时,您可以重新加载整个集合视图,当选择/取消选择单个单元格时,只需重新加载该单元格。
@objcMembers
class MainViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
@IBOutlet var collectionView: UICollectionView!
@IBOutlet var toolBar: UIToolbar?
@IBOutlet weak var selectButton: UIBarButtonItem!
var selectedCells = Set<IndexPath>()
var isSelectAllActive = false
// MARK: - Classes
override func viewDidLoad() {
super.viewDidLoad()
// Collection view
collectionView!.delegate = self
collectionView!.dataSource = self
collectionView!.allowsMultipleSelection = true
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
}
@IBAction func selectButtonTapped(_ sender: Any) {
if isSelectAllActive {
// Deselect all cells
selectedCells.removeAll()
selectButton.title = "Select all"
isSelectAllActive = false
} else {
// Select all cells
for i in 0 ..< collectionView!.numberOfItems(inSection: 0) {
self.selectedCells.insert(IndexPath(item:i, section:0))
}
selectButton.title = "Select none"
isSelectAllActive = true
}
self.collectionView.reloadData()
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 50
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell: UICollectionViewCell
cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CVCell", for: indexPath)
if self.selectedCells.contains(indexPath) {
cell.backgroundColor = .green
} else {
cell.backgroundColor = .white
}
if cell.viewWithTag(1) != nil {
let cellTitle = cell.viewWithTag(1) as! UILabel
cellTitle.text = String(indexPath.row)
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("\ndidSelectItemAt: \(indexPath.row)")
if selectedCells.contains(indexPath) {
selectedCells.remove(indexPath)
} else {
selectedCells.insert(indexPath)
}
self.collectionView.deselectItem(at: indexPath, animated: false)
self.collectionView.reloadItems(at: [indexPath])
print("selectedCells: \(selectedCells)")
}
}