Swift Calendar手动触发单元格

时间:2016-01-10 23:25:56

标签: ios swift

大家好,所以我一直在为我的应用程序制作日历。 我找到了一个在swift中完成的代码,我需要手动触发一个单元格并对其进行着色,但我还没有使它工作。 如何在我想要的某个部分触发细胞。 感谢

以下是视图的代码:

import UIKit
import EventKit

let cellReuseIdentifier = "KDCalendarDayCell"

let NUMBER_OF_DAYS_IN_WEEK = 7
let MAXIMUM_NUMBER_OF_ROWS = 6

let HEADER_DEFAULT_SIZE = 40.0

let FIRST_DAY_INDEX = 0
let NUMBER_OF_DAYS_INDEX = 1
let DATE_SELECTED_INDEX = 2

@objc protocol KDCalendarViewDataSource {

    func startDate() -> NSDate?
    func endDate() -> NSDate?

}

@objc protocol KDCalendarViewDelegate {

    optional func calendar(calendar : KDCalendarView, canSelectDate date : NSDate) -> Bool
    func calendar(calendar : KDCalendarView, didScrollToMonth date : NSDate) -> Void
    func calendar(calendar : KDCalendarView, didSelectDate date : NSDate, withEvents events: [EKEvent]) -> Void
    optional func calendar(calendar : KDCalendarView, didDeselectDate date : NSDate) -> Void
}


class KDCalendarView: UIView, UICollectionViewDataSource, UICollectionViewDelegate {

    var dataSource : KDCalendarViewDataSource?
    var delegate : KDCalendarViewDelegate?

    var direction : UICollectionViewScrollDirection = .Horizontal {
        didSet {
            if let layout = self.calendarView.collectionViewLayout as? KDCalendarFlowLayout {
                layout.scrollDirection = direction
                self.calendarView.reloadData()
            }
        }
    }

    private var startDateCache : NSDate = NSDate()
    private var endDateCache : NSDate = NSDate()
    private var startOfMonthCache : NSDate = NSDate()
    private var todayIndexPath : NSIndexPath?

    private var daysIndexPath : NSIndexPath?

    private(set) var selectedIndexPaths : [NSIndexPath] = [NSIndexPath]()
    private(set) var selectedDates : [NSDate] = [NSDate]()

    private var eventsByIndexPath : [NSIndexPath:[EKEvent]]?
    var events : [EKEvent]? {

        didSet {

            if let events = events { // If events are not null

                eventsByIndexPath = [NSIndexPath:[EKEvent]]() // Map IndexPath to Event Array

                for event in events {

                    let flags: NSCalendarUnit = [NSCalendarUnit.Month, NSCalendarUnit.Day]

                    let distanceFromStartComponent = NSCalendar.currentCalendar().components( // Get the distance of the event from the start
                        flags, fromDate:startOfMonthCache, toDate: event.startDate, options: NSCalendarOptions()
                    )

                    let indexPath = NSIndexPath(forItem: distanceFromStartComponent.day, inSection: distanceFromStartComponent.month)

                    if var eventsList : [EKEvent] = eventsByIndexPath?[indexPath] { // If we have initialized a list for this IndexPath

                        eventsList.append(event) // Simply append
                    }
                    else {

                        eventsByIndexPath?[indexPath] = [event] // Otherwise create the list with the first element

                    }

                } // [for event in events ...]

                self.calendarView.reloadData()

            } // [if let events ...]

            else {

                eventsByIndexPath = nil

            }

        } // didSet
    }

    lazy var headerView : KDCalendarHeaderView = {

        let hv = KDCalendarHeaderView(frame:CGRectZero)

        return hv

    }()

    lazy var calendarView : UICollectionView = {

        let layout = KDCalendarFlowLayout()
        layout.scrollDirection = self.direction;
        layout.minimumInteritemSpacing = 0
        layout.minimumLineSpacing = 0

        let cv = UICollectionView(frame: CGRectZero, collectionViewLayout: layout)
        cv.dataSource = self
        cv.delegate = self
        cv.pagingEnabled = true
        cv.backgroundColor = UIColor.clearColor()
        cv.showsHorizontalScrollIndicator = false
        cv.showsVerticalScrollIndicator = false
        cv.allowsMultipleSelection = true


        return cv

    }()

    override var frame: CGRect {
        didSet {

            var elementFrame = CGRect(x:0.0, y:0.0, width: self.frame.size.width, height:80.0)

            self.headerView.frame = elementFrame

            elementFrame.origin.y += elementFrame.size.height
            elementFrame.size.height = self.frame.size.height - elementFrame.size.height

            self.calendarView.frame = CGRect(x:0.0, y:80.0, width: self.frame.size.width, height:self.frame.size.height - 80.0)

            let layout = self.calendarView.collectionViewLayout as! KDCalendarFlowLayout

            self.calendarView.collectionViewLayout = layout

        }
    }



    override init(frame: CGRect) {
        super.init(frame : CGRectMake(0.0, 0.0, 200.0, 200.0))
        self.initialSetup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func awakeFromNib() {
        self.initialSetup()
    }



    // MARK: Setup 

    func initialSetup() {


        self.clipsToBounds = true

        // Register Class
        self.calendarView.registerClass(KDCalendarDayCell.self, forCellWithReuseIdentifier: cellReuseIdentifier)


        self.addSubview(self.headerView)
        self.addSubview(self.calendarView)
    }



    // MARK: UICollectionViewDataSource

    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {

        // Set the collection view to the correct layout
        let layout = self.calendarView.collectionViewLayout as! UICollectionViewFlowLayout
        layout.itemSize = CGSizeMake(self.calendarView.frame.size.width / CGFloat(NUMBER_OF_DAYS_IN_WEEK), (self.calendarView.frame.size.height - layout.headerReferenceSize.height) / CGFloat(MAXIMUM_NUMBER_OF_ROWS))

        self.calendarView.collectionViewLayout = layout


        if let  startDate = self.dataSource?.startDate(),
                endDate = self.dataSource?.endDate() {

            startDateCache = startDate
            endDateCache = endDate

            // check if the dates are in correct order
            if NSCalendar.currentCalendar().compareDate(startDate, toDate: endDate, toUnitGranularity: NSCalendarUnit.Nanosecond) != NSComparisonResult.OrderedAscending {
                return 0
            }

            // discart day and minutes so that they round off to the first of the month
            let dayOneComponents = NSCalendar.currentCalendar().components( [NSCalendarUnit.Era, NSCalendarUnit.Year, NSCalendarUnit.Month], fromDate: startDateCache)

            // create a GMT set calendar so that the
            if let  gmtCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian),
                    gmtTimeZone = NSTimeZone(abbreviation: "GMT") {

                    gmtCalendar.timeZone = gmtTimeZone

                    if let dateFromDayOneComponents = gmtCalendar.dateFromComponents(dayOneComponents) {

                        startOfMonthCache = dateFromDayOneComponents

                        let today = NSDate()

                        if  startOfMonthCache.compare(today) == NSComparisonResult.OrderedAscending &&
                            endDateCache.compare(today) == NSComparisonResult.OrderedDescending {

                                let differenceFromTodayComponents = NSCalendar.currentCalendar().components([NSCalendarUnit.Month, NSCalendarUnit.Day], fromDate: startOfMonthCache, toDate: NSDate(), options: NSCalendarOptions())

                                self.todayIndexPath = NSIndexPath(forItem: differenceFromTodayComponents.day, inSection: differenceFromTodayComponents.month)

                        }



                        let differenceComponents = NSCalendar.currentCalendar().components(NSCalendarUnit.Month, fromDate: startDateCache, toDate: endDateCache, options: NSCalendarOptions())


                        return differenceComponents.month + 1 // if we are for example on the same month and the difference is 0 we still need 1 to display it
                    }

            }

        }

        return 0
    }

    var monthInfo : [Int:[Int]] = [Int:[Int]]()

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

        let monthOffsetComponents = NSDateComponents()

        // offset by the number of months
        monthOffsetComponents.month = section;

        if let correctMonthForSectionDate = NSCalendar.currentCalendar().dateByAddingComponents(monthOffsetComponents, toDate: startOfMonthCache, options: NSCalendarOptions()) {

            let numberOfDaysInMonth = NSCalendar.currentCalendar().rangeOfUnit(NSCalendarUnit.Day, inUnit: NSCalendarUnit.Month, forDate: correctMonthForSectionDate).length

            var firstWeekdayOfMonthIndex = NSCalendar.currentCalendar().component(NSCalendarUnit.Weekday, fromDate: correctMonthForSectionDate)
            firstWeekdayOfMonthIndex = firstWeekdayOfMonthIndex - 1 // firstWeekdayOfMonthIndex should be 0-Indexed
            firstWeekdayOfMonthIndex = (firstWeekdayOfMonthIndex + 6) % 7 // push it modularly so that we take it back one day so that the first day is Monday instead of Sunday which is the default

            monthInfo[section] = [firstWeekdayOfMonthIndex, numberOfDaysInMonth]

            return NUMBER_OF_DAYS_IN_WEEK * MAXIMUM_NUMBER_OF_ROWS // 7 x 6 = 42
        }

        return 0

    }

    let test  = [2,4,6,9,10,23]

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

        let dayCell = collectionView.dequeueReusableCellWithReuseIdentifier(cellReuseIdentifier, forIndexPath: indexPath) as! KDCalendarDayCell

        let currentMonthInfo : [Int] = monthInfo[indexPath.section]! // we are guaranteed an array by the fact that we reached this line (so unwrap)

        let fdIndex = currentMonthInfo[FIRST_DAY_INDEX]
        let nDays = currentMonthInfo[NUMBER_OF_DAYS_INDEX]

        if indexPath.item >= fdIndex &&
            indexPath.item < fdIndex + nDays {

            dayCell.textLabel.text = String(indexPath.item - fdIndex + 1)
            dayCell.hidden = false

                if(indexPath.item - fdIndex + 1 == 2){
                    //dayCell.backgroundColor = UIColor.redColor()
                    dayCell.isFinished_d = true
                }
                for tests in test{
                    if((indexPath.item - fdIndex + 1) == tests){
                       print("At day \(dates())\(indexPath.item - fdIndex + 1) the workout has been finished")


                       //From here i need to color the cell
                    }
                }
                //print(dates()+String(indexPath.item - fdIndex + 1))
        }
        else {
            dayCell.textLabel.text = ""
            dayCell.hidden = true
        }

        dayCell.selected = selectedIndexPaths.contains(indexPath)

        if indexPath.section == 0 && indexPath.item == 0 {
            self.scrollViewDidEndDecelerating(collectionView)
        }

        if let idx = self.todayIndexPath {
            dayCell.isToday = (idx.section == indexPath.section && idx.item + fdIndex == indexPath.item)
        }


        if let eventsForDay = self.eventsByIndexPath?[indexPath] {
            //print(eventsForDay[0])
            print(dayCell.eventsCount = eventsForDay.count)

        } else {
            dayCell.eventsCount = 0
        }

        return dayCell
    }

    // MARK: UIScrollViewDelegate
    func dates()->String{
        var _days = ""
        let cvbounds = self.calendarView.bounds

        var page : Int = Int(floor(self.calendarView.contentOffset.x / cvbounds.size.width))

        page = page > 0 ? page : 0

        let monthsOffsetComponents = NSDateComponents()
        monthsOffsetComponents.month = page


        if let yearDate = NSCalendar.currentCalendar().dateByAddingComponents(monthsOffsetComponents, toDate: self.startOfMonthCache, options: NSCalendarOptions()) {



            let month = NSCalendar.currentCalendar().component(NSCalendarUnit.Month, fromDate: yearDate)

            //let monthName = NSDateFormatter().monthSymbols[(month-1) % 12] // 0 indexed array

            let year = NSCalendar.currentCalendar().component(NSCalendarUnit.Year, fromDate: yearDate)

            //print(month,monthName,year)
            _days = "\(year)-\(month)-"
        }
    return _days
    }

    func scrollViewDidEndDecelerating(scrollView: UIScrollView) {

        let cvbounds = self.calendarView.bounds

        var page : Int = Int(floor(self.calendarView.contentOffset.x / cvbounds.size.width))

        page = page > 0 ? page : 0

        let monthsOffsetComponents = NSDateComponents()
        monthsOffsetComponents.month = page


        if let yearDate = NSCalendar.currentCalendar().dateByAddingComponents(monthsOffsetComponents, toDate: self.startOfMonthCache, options: NSCalendarOptions()) {

            let month = NSCalendar.currentCalendar().component(NSCalendarUnit.Month, fromDate: yearDate)

            let monthName = NSDateFormatter().monthSymbols[(month-1) % 12] // 0 indexed array

                let year = NSCalendar.currentCalendar().component(NSCalendarUnit.Year, fromDate: yearDate)


                self.headerView.monthLabel.text = monthName + " " + String(year)


                if let delegate = self.delegate {

                    delegate.calendar(self, didScrollToMonth: yearDate)

                }

        }
    }



    // MARK: UICollectionViewDelegate

    private var dateBeingSelectedByUser : NSDate?
    func collectionView(collectionView: UICollectionView, shouldSelectItemAtIndexPath indexPath: NSIndexPath) -> Bool {

        let currentMonthInfo : [Int] = monthInfo[indexPath.section]!
        let firstDayInMonth = currentMonthInfo[0]

        let offsetComponents = NSDateComponents()
        offsetComponents.month = indexPath.section
        offsetComponents.day = indexPath.item - firstDayInMonth

        if let dateUserSelected = NSCalendar.currentCalendar().dateByAddingComponents(offsetComponents, toDate: self.startOfMonthCache, options: NSCalendarOptions()) {

            dateBeingSelectedByUser = dateUserSelected

            // Optional protocol method
            if let canSelectFromDelegate = delegate?.calendar?(self, canSelectDate: dateUserSelected) {
                return canSelectFromDelegate

            }

            return true // it can select any date by default

        }

        return false // if date is out of scope

    }

    func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {

        if let
            delegate = self.delegate,
            index = selectedIndexPaths.indexOf(indexPath),
            dateSelectedByUser = dateBeingSelectedByUser {

                delegate.calendar?(self, didDeselectDate: dateSelectedByUser)

                selectedIndexPaths.removeAtIndex(index)
                selectedDates.removeAtIndex(index)

        }

    }

    func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

        if let
            delegate = self.delegate,
            dateSelectedByUser = dateBeingSelectedByUser {

                var eventsArray : [EKEvent] = [EKEvent]()

                if let eventsForDay = self.eventsByIndexPath?[indexPath] {
                    eventsArray = eventsForDay;
                }


                delegate.calendar(self, didSelectDate: dateSelectedByUser, withEvents: eventsArray)

                // Update model
                selectedIndexPaths.append(indexPath)
                selectedDates.append(dateSelectedByUser)

        }
    }


    func reloadData() {
        self.calendarView.reloadData()
    }

}

以下是单元格的代码:

import UIKit

let cellColorDefault = UIColor(white: 0.0, alpha: 0.1)
let cellColorToday = UIColor(red: 254.0/255.0, green: 73.0/255.0, blue: 64.0/255.0, alpha: 0.3)
let borderColor = UIColor(red: 254.0/255.0, green: 73.0/255.0, blue: 64.0/255.0, alpha: 0.8)

class KDCalendarDayCell: UICollectionViewCell {

    var eventsCount = 0 {
        didSet {
            for sview in self.dotsView.subviews {
                sview.removeFromSuperview()
            }

            let stride = self.dotsView.frame.size.width / CGFloat(eventsCount+1)
            let viewHeight = self.dotsView.frame.size.height
            let halfViewHeight = viewHeight / 2.0

            for var i = 0 ; i < eventsCount ; i++ {
                let frm = CGRect(x: (stride+1.0) - halfViewHeight, y: 0.0, width: viewHeight, height: viewHeight)
                let circle = UIView(frame: frm)
                circle.layer.cornerRadius = halfViewHeight
                circle.backgroundColor = borderColor
                self.dotsView.addSubview(circle)
            }
        }
    }

    var test : Bool = false {
        didSet {
        self.pBackgroundView.backgroundColor = cellColorToday
        }
    }

    var isToday : Bool = false {

        didSet {

            if isToday == true {
                self.pBackgroundView.backgroundColor = cellColorToday
            }
            else {
                self.pBackgroundView.backgroundColor = cellColorDefault
            }
        }
    }

    var isFinished_d : Bool = false {

        didSet {

            if isToday == true {
                self.pBackgroundView.backgroundColor = cellColorToday
            }
            else {
                self.pBackgroundView.backgroundColor = cellColorDefault
            }
        }
    }

    override var selected : Bool {

        didSet {

            if selected == true {
                self.pBackgroundView.layer.borderWidth = 2.0

            }
            else {
                self.pBackgroundView.layer.borderWidth = 0.0
            }

        }
    }

     lazy var pBackgroundView : UIView = {

        var vFrame = CGRectInset(self.frame, 3.0, 3.0)

        let view = UIView(frame: vFrame)

        view.layer.cornerRadius = 4.0

        view.layer.borderColor = borderColor.CGColor
        view.layer.borderWidth = 0.0

        view.center = CGPoint(x: self.bounds.size.width * 0.5, y: self.bounds.size.height * 0.5)

        view.backgroundColor = cellColorDefault


        return view
    }()

    lazy var textLabel : UILabel = {

        let lbl = UILabel()
        lbl.textAlignment = NSTextAlignment.Center
        lbl.textColor = UIColor.darkGrayColor()

        return lbl

    }()

    lazy var dotsView : UIView = {

        let frm = CGRect(x: 8.0, y: self.frame.size.width - 10.0 - 4.0, width: self.frame.size.width - 16.0, height: 8.0)
        let dv = UIView(frame: frm)


        return dv

    }()

    override init(frame: CGRect) {

        super.init(frame: frame)


        self.addSubview(self.pBackgroundView)

        self.textLabel.frame = self.bounds
        self.addSubview(self.textLabel)

        self.addSubview(dotsView)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }


}

0 个答案:

没有答案