Coder Social home page Coder Social logo

jzcalendarweekview's Introduction



Build Status CocoaPods Platform Swift 4.2 license MIT

iOS Calendar Week/Day View in Swift

Inspired from WRCalendarView (https://github.com/wayfinders/WRCalendarView)

Features

  • X-Day per Page (Day view: 1-day, 3-day view, weekview: 7-day)
  • Two Scroll types: One-Day scroll (scroll a section) or Page scroll
  • Two Types of Long Press Gestures: Add a new event & Move an existing event
  • Events display on calendar view (supports events with conflict time and events crossing few days)
  • Support all device orientations (including iPhone X Landscape) and iPad (Slide Over and Split View)
  • Customise your own current timeline
  • All-Day Events

Usage

ViewController

In your viewController, you only need do few things.

  1. Setup your own custom calendarWeekView in viewDidLoad
calendarWeekView.setupCalendar(numOfDays: 7,
                               setDate: Date(),
                               allEvents: JZWeekViewHelper.getIntraEventsByDate(originalEvents: events),
                               scrollType: .pageScroll,
                               firstDayOfWeek: .Monday)
  1. Override viewWillTransition and call viewTransitionHandler in JZWeekViewHelper to support all device orientations
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    JZWeekViewHelper.viewTransitionHandler(to: size, weekView: calendarWeekView)
}
  1. Setup your own custom flowLayout style in viewDidLoad (optional)
calendarWeekView.updateFlowLayout(JZWeekViewFlowLayout(hourHeight: 50, rowHeaderWidth: 50, columnHeaderHeight: 50, hourGridDivision: JZHourGridDivision.noneDiv))

JZBaseWeekView

Create your own WeekView class inheriting from JZBaseWeekView, and you should override the following functions.

  1. Register function: Register your own UICollectionReusableView here. (CollectionViewCell, SupplementaryView or DecorationView)
override func registerViewClasses() {
    super.registerViewClasses()

    // Register CollectionViewCell
    self.collectionView.register(UINib(nibName: "EventCell", bundle: nil), forCellWithReuseIdentifier: "EventCell")

    // Register DecorationView: must provide corresponding JZDecorationViewKinds
    self.flowLayout.register(BlackGridLine.self, forDecorationViewOfKind: JZDecorationViewKinds.verticalGridline)
    self.flowLayout.register(BlackGridLine.self, forDecorationViewOfKind: JZDecorationViewKinds.horizontalGridline)

    // Register SupplementrayView: must override collectionView viewForSupplementaryElementOfKind
    collectionView.register(RowHeader.self, forSupplementaryViewOfKind: JZSupplementaryViewKinds.rowHeader, withReuseIdentifier: "RowHeader")
}

If you want to use your own supplementryView (including your current timeline), you should register it and override the following function

override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView
  1. CollectionView cellForItemAt: Use your custom collectionViewCell
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let date = flowLayout.dateForColumnHeader(at: indexPath)
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: EventCell.className, for: indexPath) as! EventCell
    cell.updateView(event: allEventsBySection[date]![indexPath.row] as! Event)
    return cell
}

JZLongPressView

This view is inheriated from JZBaseWeekView and implements the long press gestures. You can simply follow the setup rules of JZBaseWeekView.
In order to achieve the long press gestures, you should implement the JZLongPressViewDelegate and JZLongPressViewDataSource in your ViewController.

public protocol JZLongPressViewDelegate: class {
    /// When addNew long press gesture ends, this function will be called.
    func weekView(_ weekView: JZLongPressWeekView, didEndAddNewLongPressAt startDate: Date)
    /// When Move long press gesture ends, this function will be called.
    func weekView(_ weekView: JZLongPressWeekView, editingEvent: JZBaseEvent, didEndMoveLongPressAt startDate: Date)
    /// Sometimes the longPress will be cancelled because some curtain reason.
    func weekView(_ weekView: JZLongPressWeekView, longPressType: JZLongPressWeekView.LongPressType, didCancelLongPressAt startDate: Date)
}

public protocol JZLongPressViewDataSource: class {
    /// Implement this function to customise your own AddNew longPressView
    func weekView(_ weekView: JZLongPressWeekView, viewForAddNewLongPressAt startDate: Date) -> UIView
    /// Implement this function to customise your own Move longPressView
    func weekView(_ weekView: JZLongPressWeekView, movingCell: UICollectionViewCell, viewForMoveLongPressAt startDate: Date) -> UIView
}

Also, you should provide the long press types and there are some other properties you can change.

calendarWeekView.longPressDelegate = self
calendarWeekView.longPressDataSource = self
calendarWeekView.longPressTypes = [.addNew, .move]

// Optional
calendarWeekView.addNewDurationMins = 120
calendarWeekView.moveTimeMinInterval = 15

If you want to use the move type long press, you have to inherit your UICollectionViewCell from JZLongPressEventCell to allow retrieving editing JZBaseEvent because of UICollectionView reuse problem. Also, remember to set your cell backgroundColor in cell contentView.

JZBaseEvent

In JZCalendarWeekView, the data model is using [Date: [Event]] dictionary because for each day (a section in collectionView), there might be some events.

A static function called getIntraEventsByDate provided in JZWeekViewHelper allow you to tranform your events list into [Date: [Event]] dictionary.

open class func getIntraEventsByDate<T: JZBaseEvent>(originalEvents: [T]) -> [Date: [T]]

In order to call this function, you should create a subclass of JZBaseEvent and also implement the NSCopying protocol.
For the intraStartDate and intraEndDate in JZBaseEvent, it means that if a event crosses two days, it should be divided into two events but with different intraStartDate and intraEndDate.
eg. startDate = 180329 14:00, endDate = 180330 03:00, then two events should be generated: 1. 180329 14:00(IntraStart) - 23:59(IntraEnd) 2. 180330 00:00(IntraStart) - 03:00(IntraEnd)

All-Day Events

All-Day feature is aimed to display all-day events separately, but only events tagged isAllDay true can be shown. For those events crossing few days would better keep them isAllDay false. (Refer to Apple Calendar & Google Calendar)
In order to active all-day feature, there are only two things you need to do.

  1. Inherit your Event class from JZAllDayEvent to ensure the isAllDay variable added.
  2. In your customised CalendarViewWeekView, override the viewForSupplementaryElementOfKind and use updateView in AllDayHeader to update your all-day view with your own views. Example

For futher usage, you can also check the example project, some comments in code or just email me.

Requirements

  • iOS 9.0+
  • Xcode 10+
  • Swift 4.2

Installation

Cocoapods

JZCalendarWeekView can be added to your project by adding the following line to your Podfile:

# Latest release in CocoaPods
pod 'JZCalendarWeekView'

# If you have NOT upgraded to Swift 4.2, use the last non-swift 4.2 compatible release
pod 'JZCalendarWeekView', '0.5.1'

Todo

  • Limited date range: First Date and Last Date in CalendarView
  • DecorationView for different background views (refer to #12)
  • Theme implementation
  • New scroll type: Infinite scroll
  • Support different types of event arrangment rules

Author

Jeff Zhang, [email protected]
If you have any questions and suggestions, feel free to contact me.

License

JZCalendarWeekView is available under the MIT license. See the LICENSE for more info.

jzcalendarweekview's People

Contributors

zjfjack avatar ajnandi avatar fawxy avatar yokurin avatar tobaloidee avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.