I wish to develop a customized date picker like this:
I created a UIView that has a label to show the month, and a stack view to show the week days identify. I attempted getting the variety of days utilizing a group view, it labored simply positive to show it based on the calendar (shows the primary week day based on the calendar i.e 1st is displayed as Solar for Sept 2024) then i realised as I scroll it horizontally, the cells will get reused and I cant use it to save lots of dates.
Right here is the code for a similar:
@IBDesignable
class CustomDatePickerView: UIView {
@IBOutlet weak var contentView: UIView!
@IBOutlet weak var collectionView: UICollectionView!
var currentMonth: Int?
var currentYear: Int?
var selectedIndexPath: IndexPath?
let calendar = Calendar.present
var daysInMonthWithOffset = [Int?]()
override init(body: CGRect) {
tremendous.init(body: body)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
tremendous.init(coder: aDecoder)
commonInit()
}
personal func commonInit() {
let currentDate = Date()
currentMonth = Calendar.present.part(.month, from: currentDate)
currentYear = Calendar.present.part(.yr, from: currentDate)
let bundle = Bundle(for: kind(of: self))
bundle.loadNibNamed("CustomDatePickerView", proprietor: self, choices: nil)
addSubview(contentView)
contentView.body = bounds
contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
initCollectionView()
setupDaysInMonth()
}
personal func initCollectionView() {
let nib = UINib(nibName: "CollectionViewCell", bundle: nil)
collectionView.register(nib, forCellWithReuseIdentifier: "CollectionViewCell")
collectionView.dataSource = self
collectionView.delegate = self
// Arrange format for 7 columns (days of the week)
let format = UICollectionViewFlowLayout()
let width = contentView.bounds.width / 7
format.itemSize = CGSize(width: width, top: width)
format.minimumInteritemSpacing = 0
format.minimumLineSpacing = 0
format.scrollDirection = .horizontal
collectionView.collectionViewLayout = format
collectionView.isScrollEnabled = true
}
// Populate the times for the given month and yr
personal func setupDaysInMonth() {
if let currentYear = currentYear, let currentMonth = currentMonth {
let numDays = getNumberOfDaysInMonth(month: currentMonth, yr: currentYear)
// Get the weekday of the primary day of the month
let firstWeekday = getFirstWeekdayOfMonth(month: currentMonth, yr: currentYear)
// Create an array with non-compulsory integers to carry the times, together with offset for first weekday
daysInMonthWithOffset = Array(repeating: nil, rely: firstWeekday - 1) + Array(1...numDays).map { Non-compulsory($0) }
}
}
// Helper technique to get the variety of days in a month
personal func getNumberOfDaysInMonth(month: Int, yr: Int) -> Int {
var dateComponents = DateComponents()
dateComponents.yr = yr
dateComponents.month = month
let calendar = Calendar.present
let date = calendar.date(from: dateComponents)!
let vary = calendar.vary(of: .day, in: .month, for: date)!
return vary.rely
}
// Helper technique to get the primary weekday of the month
personal func getFirstWeekdayOfMonth(month: Int, yr: Int) -> Int {
var dateComponents = DateComponents()
dateComponents.yr = yr
dateComponents.month = month
let calendar = Calendar.present
let firstDayOfMonth = calendar.date(from: dateComponents)!
return calendar.part(.weekday, from: firstDayOfMonth)
}
}
// MARK: - UICollectionViewDataSource
extension CustomDatePickerView: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection part: Int) -> Int {
return daysInMonthWithOffset.rely // 7 further cells for the times of the week header
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as? CollectionViewCell else {
fatalError("Cannot dequeue CollectionViewCell")
}
if let day = daysInMonthWithOffset[indexPath.item] {
cell.dayLabel.textual content = "(day)"
cell.dayLabel.font = UIFont.systemFont(ofSize: 14)
// Spotlight the chosen date
if let selectedIndexPath = selectedIndexPath, selectedIndexPath == indexPath {
cell.backgroundColor = UIColor(purple: 0.918, inexperienced: 0.851, blue: 0.365, alpha: 1)
cell.layer.masksToBounds = true
cell.layer.cornerRadius = cell.bounds.width / 2
cell.dayLabel.font = UIFont.boldSystemFont(ofSize: 14)
} else {
cell.backgroundColor = .clear
}
} else {
cell.dayLabel.textual content = ""
cell.backgroundColor = .clear
}
return cell
}
}
// MARK: - UICollectionViewDelegate
extension CustomDatePickerView: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// Save the chosen index path
selectedIndexPath = indexPath
// Reload the gathering view to replace the UI
collectionView.reloadData()
}
}
This UIView is being utilized in a unique View Controller. Is my method of making the customized date picker utilizing assortment view appropriate? If sure, then how can I alter the format cells based on the calendar?