0

I am using FSCalendar in my application to show calendar and events. So my question is can we achieve events table using FSCalendar or we have to do it by using separate tableview. Thanks in adv.

I want this tableview

kalpa
  • 884
  • 1
  • 15
  • 22
  • 1
    I will go for separate tableView , The above **Screenshot** is from FSCalendar page under **Achievement of Users** , this feature is not provided with FSCalendar Lib – iOS Geek Jun 26 '18 at 04:14

2 Answers2

0
1) put tableview down to the FSCalendar view.
2) Then Get Selected Date DATA And Relaod the tableview.
Ravi Padsala
  • 126
  • 2
  • 10
0

Events list using FSCalendar To display events, here using UICollectionView, and FSCalendar is hiding and showing using UIButton.

Also month name taken from FSCalendar and displaying separately (outside of calendar view) using UILabel.

On clicking on date from calendar collection view scrolls to respective event.

enter image description here

class CalendarViewController: UIViewController {
    
    @IBOutlet var calendarMonthButton: UIButton!
    @IBOutlet var calendarMonthArrowImageView: UIImageView!
    @IBOutlet var calendarView: UIView!
    @IBOutlet var calendarViewHeightConstraint: NSLayoutConstraint!
    @IBOutlet var collectionView: UICollectionView!

    var interactor: DailyEventsCalendarBusinessLogic?
    var events = DailyEventsCalendarModel.ViewModel()
    var didFirstLoad = false
    var selectedDate: Date?
    var selectedMonth = Date()
    var highlightedMonth = Date()
    var calendar: FSCalendar!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        initCalendar()
        calendar.delegate = self
        calendar.dataSource = self
        
        calendarView.alpha = 0
        calendarView.isHidden = true
        calendarViewHeightConstraint.constant = 8
        calendarMonthArrowImageView.transform = CGAffineTransform(scaleX: 1, y: -1)        
        collectionView.register(UINib(nibName: "EventsCalendarCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "EventsCalendarCollectionViewCell")
        collectionView.register(UINib(nibName: "EventsCalendarSectionHeaderView", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "EventsCalendarSectionHeaderView")
        
        collectionView.contentInset.bottom = 100
        
        if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
            layout.sectionHeadersPinToVisibleBounds = true
        }
        
        TDMAnalytics.sendScreenAnalytics(newScreenName: "Events Calendar", screenClass: "CalendarViewController")
        
        setUpInteractor()
        interactor?.fetch(Date(), toDate: DateInRegion(selectedMonth,region: Region.current).dateAtEndOf(.month).dateAtEndOf(.day).date)
    }
    
    func initCalendar() {
        calendar = FSCalendar(frame: CGRect(x: 0, y: 0, width: self.calendarView.frame.width, height: self.calendarView.frame.height))
        calendar.alpha = 1
        calendar.center = calendarView.center
        
        let screenSize: CGRect = UIScreen.main.bounds
        if screenSize.width >= 375 {
            calendar.frame = CGRect(x: 0, y: 0, width: calendarView.frame.width-35, height: calendarView.frame.height)
        } else {
            calendar.frame = CGRect(x: 0, y: 0, width: calendarView.frame.width, height: calendarView.frame.height)
        }
        
        calendar.headerHeight = 0
        calendar.placeholderType = .none
        calendar.appearance.weekdayTextColor = .lightGray    //   weekday text color
        calendar.appearance.titleDefaultColor = .white   //   active dates color
        calendar.appearance.titleSelectionColor = .black    //   selected date text color
        calendar.appearance.titleTodayColor = .black    //  todays date text color
        calendar.appearance.todayColor = .white   // todays date circle color
        calendar.appearance.selectionColor = .lightGray   //   date selection color
        calendarView.addSubview(calendar)
        calendarCurrentPageDidChange(calendar)
    }
    
    func calendarCurrentPageDidChange(_ calendar: FSCalendar) {
        let currentPageDate = calendar.currentPage
        let month = Calendar.current.component(.month, from: currentPageDate)
        let monthName = DateFormatter().monthSymbols[month - 1].capitalized
        calendarMonthButton.setTitle(monthName, for: .normal)
    }
    
    func setUpInteractor() {
        let presenter = DailyEventsCalendarPresenter(displayable: self)
        let worker = EventListWorker()
        interactor = DailyEventsCalendarInteractor(presenter: presenter, worker: worker)
    }
 
    @IBAction func tapCalendarMonthButton(_ sender: Any) {
        toggleCalendar()
    }
    
    func toggleCalendar(hide: Bool? = nil) {
        let hiding: Bool = hide ?? !self.calendarView.isHidden
        if (hiding && self.calendarView.isHidden) || (!hiding && !self.calendarView.isHidden) {
            return
        }
        if !hiding {
            self.calendarView.isHidden = false
            self.calendarView.alpha = 0
            self.calendarView.reloadInputViews()
            self.updateCalendarLayout()
        }
        UIView.animate(withDuration: 0.2, delay: 0, options: [.curveEaseInOut], animations: {
            if hiding {
                self.calendarView.alpha = 0
                self.calendarViewHeightConstraint.constant = 8
                self.calendarMonthArrowImageView.transform = CGAffineTransform(scaleX: 1, y: -1)
                self.calendarView.reloadInputViews()
                self.updateCalendarLayout()
            } else {
                self.calendarView.alpha = 1
                self.calendarViewHeightConstraint.constant = 266
                self.calendarMonthArrowImageView.transform = .identity
                self.calendarView.reloadInputViews()
                self.updateCalendarLayout()
            }
            self.view.layoutIfNeeded()
        }) { (completed) in
            if hiding {
                self.calendarView.isHidden = true
                self.updateCalendarLayout()
            }
        }
    }
    
    func updateCalendarLayout() {
        calendarView.layoutSubviews()
        calendarView.layoutIfNeeded()
        calendar.layoutSubviews()
        calendar.layoutIfNeeded()
    }
    
    func scrollToDate(_ date: Date,animated:Bool = true) {
        var foundIdx: Int?
        for (idx,eventsDay) in events.eventsDays.enumerated() {
            if NSCalendar.current.isDate(date, inSameDayAs: eventsDay.date) {
                foundIdx = idx
            }
        }
        if let foundIdx = foundIdx {
            if let layoutAttributes = collectionView.layoutAttributesForItem(at: IndexPath(item: 0, section: foundIdx)) {
             
                collectionView.setContentOffset(CGPoint(x: 0, y: layoutAttributes.frame.origin.y - 12), animated: true)
            }
        
        } else {
            let dateDIR = DateInRegion(date,region:Region.current)
            let selectedMonthDIR = DateInRegion(selectedMonth,region:Region.current)
            if dateDIR.month == selectedMonthDIR.month && dateDIR.year == selectedMonthDIR.year {
                MBProgressHUD.showToast(toastMessage: "There are no events on this date.", duration: .short)
            }
        }
    }
    
}

extension CalendarViewController: DailyEventsCalendarDisplayable {
    func display(_ viewModel: DailyEventsCalendarModel.ViewModel) {
        
        events = viewModel
        
        collectionView.reloadData()
        
        if let startDate = events.startDate {
            selectedMonth = startDate
        }
        
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2) {
            if !self.didFirstLoad {
                self.scrollToDate(Date().dateAtStartOf(.day),animated:false)
                self.didFirstLoad = true
            }
        }
    }
    
    func displayEventWithFeed(_ event: Feed?) {
        if let feed = event {
            let controllerIdentifier = String(describing: FeedDetailViewController.self)
            let feedDetailController = UIStoryboard.controller(controllerIdentifier, storyboardName: .feedDetail) as! FeedDetailViewController
            feedDetailController.setUpInteractor()
            feedDetailController.interactor?.feed = feed
            feedDetailController.isStoreBtnHidden = !feed.showVisitBrand
            feedDetailController.type = FavoriteType.event.rawValue
            
            self.present(feedDetailController, animated: true, completion: nil)
            //self.parent?.navigationController?.pushViewController(feedDetailController, animated: true)
        }
    }
}

extension CalendarViewController: UIScrollViewDelegate {
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        toggleCalendar(hide: true)
    }
}

extension CalendarViewController: UICollectionViewDataSource {
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        let days = highlightedMonth.monthDays
        if (events.eventsDays.count > days) {
            return days
        }
        return events.eventsDays.count
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        let eventsDay = events.eventsDays[section]
        return eventsDay.events.count
    }
    
    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        if kind == UICollectionView.elementKindSectionHeader {
            if let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "EventsCalendarSectionHeaderView", for: indexPath) as? EventsCalendarSectionHeaderView {
                
                let eventsDay = events.eventsDays[indexPath.section]
                
                let date = DateInRegion(eventsDay.date, region: Region.current)
                headerView.dayLabel.text = "\(date.weekdayName(.short).uppercased())"
                headerView.dateLabel.text = "\(date.day)"
                if date.isToday {
                    headerView.dateLabelBackgroundView.isHidden = false
                    headerView.dateLabel.textColor = .black
                } else {
                    headerView.dateLabelBackgroundView.isHidden = true
                    headerView.dateLabel.textColor = .white
                }
                
                return headerView
            }
        }
       
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell  {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "EventsCalendarCollectionViewCell", for: indexPath) as! EventsCalendarCollectionViewCell
        
        let event = events.eventsDays[indexPath.section].events[indexPath.item]
        
        cell.dateLabel.isHidden = true
        
        cell.configureEvent(event)
        
        return cell
    }

}

extension CalendarViewController: UICollectionViewDelegateFlowLayout {
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let layout = collectionViewLayout as! UICollectionViewFlowLayout
        return CGSize(width: collectionView.bounds.size.width - layout.sectionInset.left - layout.sectionInset.right, height: 120)
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        return CGSize(width: 48, height: 1)
    }
}

extension CalendarViewController: UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        toggleCalendar(hide: true)
        let event = events.eventsDays[indexPath.section].events[indexPath.item]
        displayEventWithFeed(event.feed)
    }
}

extension CalendarViewController: FSCalendarDelegate, FSCalendarDataSource {
    func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
        self.scrollToDate(date.date)
    }
    
    func maximumDate(for calendar: FSCalendar) -> Date {
        var dateComponents:DateComponents = DateComponents()
        dateComponents.month = 12
        let currentCalander:Calendar = Calendar.current
        return currentCalander.date(byAdding:dateComponents, to: Date())!
    }
    
    func minimumDate(for calendar: FSCalendar) -> Date {
        var dateComponents:DateComponents = DateComponents()
        dateComponents.month = 0
        let currentCalander:Calendar = Calendar.current
        return currentCalander.date(byAdding:dateComponents, to: Date())!
    }
}

For creating FSCalendar programmatically and Customize

https://stackoverflow.com/a/75886956/15716725

khirish
  • 537
  • 1
  • 7
  • 9