ios - 如何使用 UICollectionView 的 selectItem 在 collectionView 单元格上绘图?
问题描述
我添加了我在这里工作的仓库:
https://github.com/AlexMarshall12/singleDayTimeline/tree/master/singleDayTimeline
基本上我有 900 个 collectionView 单元格(带有自定义 XIB 布局)。
let cellIdentifier = "DayCollectionViewCell"
class ViewController: UIViewController, UICollectionViewDataSource,UICollectionViewDelegate {
@IBOutlet weak var button: UIButton!
var dates = [Date?]()
var startDate: Date?
@IBOutlet weak var daysCollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
daysCollectionView.register(UINib.init(nibName: "DayCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: cellIdentifier)
let allDates = Helper.generateRandomDate(daysBack: 900, numberOf: 10)
self.dates = allDates.sorted(by: {
$0!.compare($1!) == .orderedAscending
})
startDate = self.dates.first! ?? Date()
daysCollectionView.delegate = self
daysCollectionView.dataSource = self
// Do any additional setup after loading the view, typically from a nib.
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 900
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = daysCollectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! DayCollectionViewCell
let cellDate = Calendar.current.date(byAdding: .day, value: indexPath.item, to: self.startDate!)
if Calendar.current.component(.day, from: cellDate!) == 15 {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM"
let monthString = dateFormatter.string(from: cellDate!)
cell.drawMonth(month: monthString)
}
if Calendar.current.component(.day, from: cellDate!) == 1 && Calendar.current.component(.month, from: cellDate!) == 1 {
print("drawYEAR")
cell.drawYear(year:Calendar.current.component(.year, from: cellDate!))
}
if self.dates.contains(where: { Calendar.current.isDate(cellDate!, inSameDayAs: $0!) }) {
print("same")
cell.backgroundColor = UIColor.red
} else {
print("not me")
//cell.backgroundColor = UIColor.lightGray
}
return cell
}
// func collectionView(_ collectionView: UICollectionView,
// layout collectionViewLayout: UICollectionViewLayout,
// sizeForItemAt indexPath: IndexPath) -> CGSize {
// return CGSize(width: 2, height: daysCollectionView.bounds.size.height/2 )
// }
@IBAction func buttonPressed(_ sender: Any) {
let randomIndex = Int(arc4random_uniform(UInt32(self.dates.count)))
let randomDate = self.dates[randomIndex]
let daysFrom = randomDate?.days(from: self.startDate!)
let indexPath = IndexPath(row: daysFrom!, section: 0)
// if let cell = daysCollectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as DayCollectionViewCell? {
// print("found it")
// } else {
// print("didn't find it")
// }
daysCollectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredHorizontally)
daysCollectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
}
}
然后这里是单元格:
class DayCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var arrowImage: UIImageView!
override var isSelected: Bool{
didSet{
arrowImage.isHidden = !isSelected
}
}
override func awakeFromNib() {
super.awakeFromNib()
arrowImage.isHidden = true
}
override func prepareForReuse() {
self.backgroundColor = UIColor.clear
}
func drawMonth(month: String){
}
func drawYear(year: Int){
}
}
它看起来像这样:
因此计划是,当按下该按钮时,您可以在@IBAction func buttonPressed 中看到选择并滚动到随机日期,然后在 collectionView 中选择该单元格。arrowImage.isHidden = !isSelected
然后,在覆盖 var isSelected 函数中绘制单元格的箭头。
目前,这几乎可以完美运行。当随机选择的新索引离当前索引足够远时,箭头会在所选单元格下重新绘制。我的理论是,如果索引差异足够大,则下一个单元格尚未加载/出列,因此永远不会调用 isSelected。但是我仍然不确定为什么它不能正常工作
解决方案
1- 添加一个 reloadCell 函数来改变单元格的 ui。然后你应该从函数中删除override var isSelected
和。arrowImage.isHidden = true
awakeFromNib
func reloadCell(_ isSelected:Bool){
arrowImage.isHidden = !isSelected
}
2-您应该在ViewController.swift
类上定义一个变量private var selectedIndexPath: IndexPath?
,然后您应该添加此代码以检查箭头是否隐藏。
if let selectedRow = selectedIndexPath {
cell.reloadCell(selectedRow == indexPath)
} else {
cell.reloadCell(false)
}
3-如果您像下面这样更改按钮操作功能,它将起作用。
@IBAction func buttonPressed(_ sender: Any) {
let randomIndex = Int(arc4random_uniform(UInt32(self.dates.count)))
let randomDate = self.dates[randomIndex]
let daysFrom = randomDate?.days(from: self.startDate!)
let indexPath = IndexPath(row: daysFrom!, section: 0)
self.selectedIndexPath = indexPath;
daysCollectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
daysCollectionView.reloadData()
}
- 所有代码都在这里。
ViewController.swift
import UIKit
let cellIdentifier = "DayCollectionViewCell"
class ViewController: UIViewController, UICollectionViewDataSource,UICollectionViewDelegate {
@IBOutlet weak var button: UIButton!
var dates = [Date?]()
var startDate: Date?
private var selectedIndexPath: IndexPath?
@IBOutlet weak var daysCollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
daysCollectionView.register(UINib.init(nibName: "DayCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: cellIdentifier)
let allDates = Helper.generateRandomDate(daysBack: 900, numberOf: 10)
self.dates = allDates.sorted(by: {
$0!.compare($1!) == .orderedAscending
})
startDate = self.dates.first! ?? Date()
daysCollectionView.delegate = self
daysCollectionView.dataSource = self
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 900
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = daysCollectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! DayCollectionViewCell
let cellDate = Calendar.current.date(byAdding: .day, value: indexPath.item, to: self.startDate!)
if let selectedRow = selectedIndexPath {
cell.reloadCell(selectedRow == indexPath)
} else {
cell.reloadCell(false)
}
if Calendar.current.component(.day, from: cellDate!) == 15 {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM"
let monthString = dateFormatter.string(from: cellDate!)
cell.drawMonth(month: monthString)
}
if Calendar.current.component(.day, from: cellDate!) == 1 && Calendar.current.component(.month, from: cellDate!) == 1 {
print("drawYEAR")
cell.drawYear(year:Calendar.current.component(.year, from: cellDate!))
}
if self.dates.contains(where: { Calendar.current.isDate(cellDate!, inSameDayAs: $0!) }) {
print("same")
cell.backgroundColor = UIColor.red
} else {
print("not me")
//cell.backgroundColor = UIColor.lightGray
}
return cell
}
@IBAction func buttonPressed(_ sender: Any) {
let randomIndex = Int(arc4random_uniform(UInt32(self.dates.count)))
let randomDate = self.dates[randomIndex]
let daysFrom = randomDate?.days(from: self.startDate!)
let indexPath = IndexPath(row: daysFrom!, section: 0)
self.selectedIndexPath = indexPath;
//daysCollectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredHorizontally)
daysCollectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
daysCollectionView.reloadData()
}
}
DayCollectionViewCell.swift
import UIKit
class DayCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var arrowImage: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
}
override func prepareForReuse() {
self.backgroundColor = UIColor.clear
}
func drawMonth(month: String){
}
func drawYear(year: Int){
}
func reloadCell(_ isSelected:Bool){
arrowImage.isHidden = !isSelected
}
}
推荐阅读
- python - 如何查看方法的文档或源代码而不是输入 Pycharm
- optimization - 如何在 CPLEX 优化工作室中求解二次目标?
- aws-lambda - 无服务器部署失败,stackTags 变量中出现 + 字符
- ruby - 输出重定向到文件
- mybatis - 如何在 MyBatis SELECT 查询中获取 java 枚举序数值
- php - 在 PHP 中使用 Curl 从网站获取请求 Cookie
- php - 为什么我的一些 shell_exec 有时会因管道损坏而失败,但仍会产生必要的输出?
- php - 当我单击引导按钮时,我想调用 php 插入查询
- .net - 添加项目引用错误地添加了 dll 引用
- html - 使用 VBA 单击带有数据切换和数据目标的按钮