UIcollectionview 一次选择多个单元格
Posted
技术标签:
【中文标题】UIcollectionview 一次选择多个单元格【英文标题】:UIcollection view bug of selecting more than one cells at a time 【发布时间】:2020-05-23 12:14:43 【问题描述】:我正在创建一个 7 天的日历。我正在使用包含 7 个单元格的集合视图,但是当我选择集合视图的最后一个单元格并滚动到第一个单元格时,最后一个单元格保持选中状态,并且第一个单元格也被选中。这是我得到的错误的屏幕截图。 enter image description hereenter image description here 这是我的主视图控制器中的代码
`import UIKit
import Foundation
class ScheduleViewController: UIViewController
let top = UIColor(red: 217/255, green: 30/255, blue: 133/255, alpha: 1)
let bottom = UIColor(red: 242/255, green: 56/255, blue: 15/255, alpha: 1)
let todayColor = UIColor(red: 242/255, green: 56/255, blue: 15/255, alpha: 1)
// let otherDayColor = UIColor(red: 90/255, green: 90/255, blue: 90/255, alpha: 1)
let otherDayColor = UIColor(red: 242/255, green: 56/255, blue: 15/255, alpha: 1)
var now = Date()
var day = DateFormatter()
let dateHeading: UILabel =
let heading = UILabel()
heading.text = "Date"
heading.font = UIFont(name: "Roboto-Medium", size: 20)
heading.translatesAutoresizingMaskIntoConstraints = false
heading.numberOfLines = 0
heading.adjustsFontSizeToFitWidth = true
return heading
()
fileprivate let collectionView: UICollectionView =
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.backgroundColor = .clear
cv.translatesAutoresizingMaskIntoConstraints = false
cv.register(CalendarCell.self, forCellWithReuseIdentifier: "CellID")
return cv
()
let bookButton: UIButton =
let button = UIButton(type: .system)
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle("Book", for: .normal)
button.titleLabel?.font = UIFont(name: "Roboto-Medium", size: 22)
button.layer.cornerRadius = 5
button.setTitleColor(.white, for: .normal)
return button
()
override func viewDidLoad()
super.viewDidLoad()
view.backgroundColor = .black
setupNavigationBar()
view.addSubview(bookButton)
bookButtonLayout()
view.addSubview(collectionView)
collectionViewLayout()
configureCollectionView()
collectionView.selectItem(at: IndexPath(row: 0, section: 0), animated: true, scrollPosition: [])
view.addSubview(dateHeading)
dateHeadingLayout()
let gradientWidth = (UIScreen.main.bounds.width - 40)
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [top.cgColor, bottom.cgColor]
gradientLayer.locations = [0.15, 1]
gradientLayer.startPoint = CGPoint(x: 0, y: 0)
gradientLayer.endPoint = CGPoint(x: 1, y: 0)
gradientLayer.frame = CGRect(x: 0, y: 0, width: gradientWidth, height: 44)
gradientLayer.cornerRadius = 5
bookButton.layer.insertSublayer(gradientLayer, at: 0)
func myCalender(numDay: Int) -> Date
var dateComponents = DateComponents()
dateComponents.setValue(numDay, for: .day); // +1 day
let tomorrow = Calendar.current.date(byAdding: dateComponents, to: now)
return tomorrow!
func setupNavigationBar()
self.navigationItem.title = "Schedule"
self.navigationController?.navigationBar.prefersLargeTitles = true
self.navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
func collectionViewLayout()
collectionView.heightAnchor.constraint(equalToConstant: 85).isActive = true
collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true
collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 10).isActive = true
func configureCollectionView()
collectionView.delegate = self
collectionView.dataSource = self
func dateHeadingLayout()
dateHeading.heightAnchor.constraint(equalToConstant: 26).isActive = true
dateHeading.widthAnchor.constraint(equalToConstant: 42).isActive = true
dateHeading.bottomAnchor.constraint(equalTo: collectionView.topAnchor, constant: -5).isActive = true
dateHeading.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
func bookButtonLayout()
bookButton.heightAnchor.constraint(equalToConstant: 44).isActive = true
bookButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true
bookButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
bookButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -30).isActive = true
extension ScheduleViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
return CGSize(width: 70, height: 75)
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
return 7
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
let cell = collectionView.cellForItem(at: indexPath) as? CalendarCell
if cell?.isSelected == true
cell?.backgroundColor = todayColor
cell?.dateLabel.textColor = UIColor.white.withAlphaComponent(1)
cell?.dayLabel.textColor = UIColor.white.withAlphaComponent(1)
cell?.isOpaque = false
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath)
let cell = collectionView.cellForItem(at: indexPath) as? CalendarCell
if cell?.isSelected == false
cell?.backgroundColor = .clear
cell?.dateLabel.textColor = UIColor.white.withAlphaComponent(0.5)
cell?.dayLabel.textColor = UIColor.white.withAlphaComponent(0.5)
cell?.isOpaque = false
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CellID", for: indexPath) as! CalendarCell
cell.layer.cornerRadius = 5
cell.dateLabel.textColor = UIColor.white.withAlphaComponent(0.5)
cell.dayLabel.textColor = UIColor.white.withAlphaComponent(0.5)
cell.isOpaque = false
if cell.isSelected == true
cell.backgroundColor = todayColor
cell.dateLabel.textColor = UIColor.white.withAlphaComponent(1)
cell.dayLabel.textColor = UIColor.white.withAlphaComponent(1)
cell.isOpaque = false
if indexPath.row == 0
cell.dayLabel.text = (day.shortWeekdaySymbols[Calendar.current.component(.weekday, from: Date()) - 1])
cell.dateLabel.text = now.string(format: "dd")
else if indexPath.row == 1
cell.dayLabel.text = (day.shortWeekdaySymbols[Calendar.current.component(.weekday, from: myCalender(numDay: 1)) - 1])
cell.dateLabel.text = myCalender(numDay: 1).string(format: "dd")
else if indexPath.row == 2
cell.dayLabel.text = (day.shortWeekdaySymbols[Calendar.current.component(.weekday, from: myCalender(numDay: 2)) - 1])
cell.dateLabel.text = myCalender(numDay: 2).string(format: "dd")
else if indexPath.row == 3
cell.dayLabel.text = (day.shortWeekdaySymbols[Calendar.current.component(.weekday, from: myCalender(numDay: 3)) - 1])
cell.dateLabel.text = myCalender(numDay: 3).string(format: "dd")
else if indexPath.row == 4
cell.dayLabel.text = (day.shortWeekdaySymbols[Calendar.current.component(.weekday, from: myCalender(numDay: 4)) - 1])
cell.dateLabel.text = myCalender(numDay: 4).string(format: "dd")
else if indexPath.row == 5
cell.dayLabel.text = (day.shortWeekdaySymbols[Calendar.current.component(.weekday, from: myCalender(numDay: 5)) - 1])
cell.dateLabel.text = myCalender(numDay: 5).string(format: "dd")
else if indexPath.row == 6
cell.dayLabel.text = (day.shortWeekdaySymbols[Calendar.current.component(.weekday, from: myCalender(numDay: 6)) - 1])
cell.dateLabel.text = myCalender(numDay: 6).string(format: "dd")
cell.isSelected = (cellStatus[indexPath.row] as? Bool) ?? false
return cell
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat
return 5
extension Date
func string(format: String) -> String
let formatter = DateFormatter()
formatter.timeZone = .current
formatter.dateFormat = format
formatter.shortWeekdaySymbols = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
return formatter.string(from: self)
`
这是我的自定义日历单元代码
`import UIKit
class CalendarCell: UICollectionViewCell
let dateLabel: UILabel =
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.font = UIFont(name: "Roboto-Medium", size: 30)
label.textColor = .white
label.textAlignment = .center
label.adjustsFontSizeToFitWidth = true
label.numberOfLines = 0
return label
()
let dayLabel: UILabel =
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.font = UIFont(name: "Roboto-Medium", size: 20)
label.textColor = .white
label.textAlignment = .center
label.adjustsFontSizeToFitWidth = true
label.numberOfLines = 0
return label
()
override init(frame: CGRect)
super.init(frame: frame)
contentView.layer.cornerRadius = 5
contentView.addSubview(dayLabel)
dayLabelLayout()
contentView.addSubview(dateLabel)
dateLabelLayout()
required init?(coder: NSCoder)
fatalError("init(coder:) has not been implemented")
func dateLabelLayout()
dateLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 5).isActive = true
dateLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -5).isActive = true
dateLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 5).isActive = true
dateLabel.bottomAnchor.constraint(equalTo: dayLabel.topAnchor).isActive = true
func dayLabelLayout()
dayLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -5).isActive = true
dayLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -5).isActive = true
dayLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 5).isActive = true
dayLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
`
【问题讨论】:
您找到解决方案了吗? 【参考方案1】:那个单元格被重用而不是被选中......但是由于重用......它的 backgroundColor , dateLabel , dayLabel 和 isOpaque 改变了
在您的CalendarCell
中.. 使用未选中单元格的默认值覆盖此函数..
override func prepareForReuse()
super.prepareForReuse()
backgroundColor = .white//defaultValue
dateLabel.textColor = UIColor.white.withAlphaComponent(1) // default value
cell?.dayLabel.textColor = UIColor.white.withAlphaComponent(1) // default value
cell?.isOpaque = false // default value
【讨论】:
永远不要!忘记打电话给超级! super.prepareForReuse()以上是关于UIcollectionview 一次选择多个单元格的主要内容,如果未能解决你的问题,请参考以下文章
在 UIcollectionview 中使多个单元格出列的方法
一个UIViewController中的多个UICollectionView数据源
UICollectionView 在单元格上拖动手指以选择它们