22.7 C
New York
Thursday, September 19, 2024

ios – How you can develop customized date picker view utilizing uikit?


I wish to develop a customized date picker like this:

Customized Date Picker View

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 nice to show it in response to the calendar (shows the primary week day in response to 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 avoid wasting 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.element(.month, from: currentDate)
     currentYear = Calendar.present.element(.12 months, 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 structure for 7 columns (days of the week)
     let structure = UICollectionViewFlowLayout()
     let width = contentView.bounds.width / 7
     structure.itemSize = CGSize(width: width, peak: width)
     structure.minimumInteritemSpacing = 0
     structure.minimumLineSpacing = 0
     structure.scrollDirection = .horizontal
     collectionView.collectionViewLayout = structure
     collectionView.isScrollEnabled = true
 }
 
 // Populate the times for the given month and 12 months
 personal func setupDaysInMonth() {
     if let currentYear = currentYear, let currentMonth = currentMonth {
         let numDays = getNumberOfDaysInMonth(month: currentMonth, 12 months: currentYear)
         // Get the weekday of the primary day of the month
         let firstWeekday = getFirstWeekdayOfMonth(month: currentMonth, 12 months: currentYear)
         // Create an array with elective integers to carry the times, together with offset for first weekday
         daysInMonthWithOffset = Array(repeating: nil, rely: firstWeekday - 1) + Array(1...numDays).map { Optionally available($0) }
     }
 }
 
 // Helper methodology to get the variety of days in a month
 personal func getNumberOfDaysInMonth(month: Int, 12 months: Int) -> Int {
     var dateComponents = DateComponents()
     dateComponents.12 months = 12 months
     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 methodology to get the primary weekday of the month
 personal func getFirstWeekdayOfMonth(month: Int, 12 months: Int) -> Int {
     var dateComponents = DateComponents()
     dateComponents.12 months = 12 months
     dateComponents.month = month
     let calendar = Calendar.present
     let firstDayOfMonth = calendar.date(from: dateComponents)!
     return calendar.element(.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(pink: 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 special View Controller. Is my method of making the customized date picker utilizing assortment view appropriate? If sure, then how can I regulate the structure cells in response to the calendar?

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles