Don_Mag

Updated Booking / Calendar cell

Nov 19th, 2020
1,249
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. class BookingController: UIViewController, UITableViewDelegate, UITableViewDataSource {
  2.  
  3.     // NEVER do something like this!!!
  4.     //  create a UITableViewCell subclass
  5.     //let calendarCell = UITableViewCell()
  6.    
  7.     override func viewDidLoad() {
  8.         super.viewDidLoad()
  9.         view.backgroundColor = .gray // Manager.Colors.dark
  10.        
  11.         if let img = UIImage(named: "Background Image") {
  12.             addBackgroundImage(image: img)
  13.         }
  14.         setupTableContent()
  15.     }
  16.    
  17.     private func addBackgroundImage(image: UIImage) {
  18.         let backgroundImage = UIImageView(image: image)
  19.         backgroundImage.frame = view.bounds
  20.         backgroundImage.alpha = 0.5
  21.         view.addSubview(backgroundImage)
  22.     }
  23.    
  24.     override var preferredStatusBarStyle: UIStatusBarStyle { .lightContent }
  25.    
  26.     private func setupTableContent() {
  27.         let tableView = UITableView()
  28.         tableView.backgroundColor = .clear
  29.         tableView.delegate = self
  30.         tableView.dataSource = self
  31.         tableView.translatesAutoresizingMaskIntoConstraints =  false
  32.         tableView.estimatedRowHeight = 80
  33.         tableView.rowHeight = UITableView.automaticDimension
  34.         view.addSubview(tableView)
  35.        
  36.         // register CalendarCell class
  37.         tableView.register(CalendarCell.self, forCellReuseIdentifier: "calendarCell")
  38.        
  39.         [tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
  40.          tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
  41.          tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
  42.          tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)].forEach({$0.isActive = true})
  43.     }
  44.    
  45.     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 1 }
  46.    
  47.     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  48.         // dequeue a CalendarCell and set its Data
  49.         let cell = tableView.dequeueReusableCell(withIdentifier: "calendarCell", for: indexPath) as! CalendarCell
  50.         cell.initData()
  51.         return cell
  52.     }
  53.    
  54.     func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { UIView() }
  55. }
  56.  
  57. // custom table view cell
  58. class CalendarCell: UITableViewCell {
  59.  
  60.     let calendarView = CalendarView()
  61.  
  62.     // we will set the .constant on this constraint to set the height of the
  63.     //  calendarView (and thus the height of the collection view)
  64.     var calendarViewHeightConstraint: NSLayoutConstraint!
  65.    
  66.     override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
  67.         super.init(style: style, reuseIdentifier: reuseIdentifier)
  68.         commonInit()
  69.     }
  70.     required init?(coder: NSCoder) {
  71.         super.init(coder: coder)
  72.         commonInit()
  73.     }
  74.     func commonInit() -> Void {
  75.        
  76.         calendarView.translatesAutoresizingMaskIntoConstraints = false
  77.         contentView.addSubview(calendarView)
  78.        
  79.         calendarView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
  80.         calendarView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
  81.         calendarView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
  82.        
  83.         // bottom anchor needs to have Priority less than required to avoid auto-layout complaints
  84.         let c = calendarView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
  85.         c.priority = .defaultHigh
  86.         c.isActive = true
  87.  
  88.         // initial height constant doesn't matter... it will be changed when we set the data
  89.         calendarViewHeightConstraint = calendarView.heightAnchor.constraint(equalToConstant: 10.0)
  90.         calendarViewHeightConstraint.isActive = true
  91.        
  92.     }
  93.  
  94.     var m: Int = 0 // tiene traccia del mese
  95.     var y: Int = 0 // tiene traccia dell'anno
  96.     var totalCellsNeeded: Int = 0 // number of cell
  97.  
  98.     func initData() {
  99.         let calendar = Calendar.current
  100.        
  101.         m = Calendar.current.component(.month, from: Date())
  102.         y = Calendar.current.component(.year, from: Date())
  103.        
  104.         let dateComponents = DateComponents(year: y, month: m)
  105.        
  106.         guard let startDate = calendar.date(from: dateComponents) else { fatalError("Something is wrong with the date!") }
  107.         guard let range = calendar.range(of: .day, in: .month, for: startDate) else { fatalError("Something is wrong with the date!") }
  108.        
  109.         let numberOfDaysInMonth = range.count
  110.         let startDayOfWeek = Calendar.current.component(.weekday, from: startDate)
  111.        
  112.         totalCellsNeeded = numberOfDaysInMonth + (startDayOfWeek - 1)
  113.        
  114.         let numRows = Int(ceil(Double(totalCellsNeeded) / Double(7)))
  115.        
  116.         // we now know the Height needed for the collection view
  117.         //  you said your calendar cell height is 75, so...
  118.         //  cvHeight = numRows * 75
  119.  
  120.         calendarViewHeightConstraint.constant = CGFloat(numRows * 75)
  121.  
  122.         // give these values to the calendarView to be used
  123.         //  for the collection view data
  124.         calendarView.startDayOfWeek = startDayOfWeek
  125.         calendarView.totalCellsNeeded = totalCellsNeeded
  126.        
  127.  
  128.     }
  129.  
  130. }
  131.  
  132. // CALENDAR VIEW
  133.  
  134. class CalendarView: UIView, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
  135.    
  136.     // these are set by the cell class
  137.     var startDayOfWeek: Int = 0
  138.     var totalCellsNeeded: Int = 0 // number of cell
  139.    
  140.     override init(frame: CGRect) {
  141.         super.init(frame: frame)
  142.         backgroundColor = .red
  143.        
  144.         let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
  145.         collectionView.delegate = self
  146.         collectionView.dataSource = self
  147.         collectionView.translatesAutoresizingMaskIntoConstraints = false
  148.         collectionView.backgroundColor = .clear
  149.         addSubview(collectionView)
  150.        
  151.         collectionView.register(DaysCell.self, forCellWithReuseIdentifier: "cellDay")
  152.        
  153.         collectionView.topAnchor.constraint(equalTo: topAnchor).isActive = true
  154.         collectionView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
  155.         collectionView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
  156.         collectionView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
  157.        
  158.         // no height anchor
  159.         //collectionView.heightAnchor.constraint(equalToConstant: 200).isActive = true
  160.        
  161.     }
  162.    
  163.     required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
  164.    
  165.     func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
  166.         totalCellsNeeded
  167.     }
  168.    
  169.     func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
  170.         let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellDay", for: indexPath) as! DaysCell
  171.  
  172.         // startDayOfWeek is 1-based
  173.         cell.populateCell(indexPath.item - (startDayOfWeek - 1))
  174.  
  175.         return cell
  176.     }
  177.    
  178.     func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
  179.         .init(width: collectionView.frame.width / 7, height: 75)
  180.     }
  181.    
  182.     func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { 0 }
  183.    
  184.     func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { 0 }
  185. }
  186.  
  187. // Day CELL
  188.  
  189. class DaysCell: UICollectionViewCell {
  190.     private let dayLbl = UILabel()
  191.    
  192.     override init(frame: CGRect) {
  193.         super.init(frame: frame)
  194.        
  195.         dayLbl.translatesAutoresizingMaskIntoConstraints = false
  196.         addSubview(dayLbl)
  197.        
  198.         dayLbl.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
  199.         dayLbl.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
  200.     }
  201.    
  202.     required init?(coder: NSCoder) {
  203.         fatalError("init(coder:) has not been implemented")
  204.     }
  205.    
  206.     func populateCell(_ i: Int) -> Void {
  207.         if i >= 0 {
  208.             dayLbl.text = "\(i + 1)"
  209.         }
  210.     }
  211. }
  212.  
RAW Paste Data