diff --git a/Example/JZCalendarWeekViewExample.xcodeproj/project.pbxproj b/Example/JZCalendarWeekViewExample.xcodeproj/project.pbxproj index e9eb6c6..e4f1fe9 100644 --- a/Example/JZCalendarWeekViewExample.xcodeproj/project.pbxproj +++ b/Example/JZCalendarWeekViewExample.xcodeproj/project.pbxproj @@ -518,11 +518,11 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = XRYH9M2JN7; + DEVELOPMENT_TEAM = L85MD8WTSB; INFOPLIST_FILE = "$(SRCROOT)/JZCalendarWeekViewExample/Supporting Files/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.zjfjack.JZCalendarWeekViewExample; + PRODUCT_BUNDLE_IDENTIFIER = com.midrive.JZCalendarWeekViewExample; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -535,11 +535,11 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = XRYH9M2JN7; + DEVELOPMENT_TEAM = L85MD8WTSB; INFOPLIST_FILE = "$(SRCROOT)/JZCalendarWeekViewExample/Supporting Files/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.zjfjack.JZCalendarWeekViewExample; + PRODUCT_BUNDLE_IDENTIFIER = com.midrive.JZCalendarWeekViewExample; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/JZCalendarWeekView.podspec b/JZCalendarWeekView.podspec index 3080cb1..c5ec799 100644 --- a/JZCalendarWeekView.podspec +++ b/JZCalendarWeekView.podspec @@ -1,11 +1,11 @@ Pod::Spec.new do |s| s.name = "JZCalendarWeekView" - s.version = "0.7.1" + s.version = "0.7.3" s.summary = "Calendar Week & Day View in iOS Swift" - s.homepage = "https://github.com/zjfjack/JZCalendarWeekView" + s.homepage = "https://github.com/midrive/JZCalendarWeekView" s.license = { :type => "MIT", :file => "LICENSE" } s.author = { "Jeff Zhang" => "zekejeff@gmail.com" } s.platform = :ios, "9.0" - s.source = { :git => "https://github.com/zjfjack/JZCalendarWeekView.git", :tag => s.version } + s.source = { :git => "https://github.com/fawxy/JZCalendarWeekView.git", :tag => s.version } s.source_files = "JZCalendarWeekView/**/*.swift" end diff --git a/JZCalendarWeekView/JZBaseWeekView.swift b/JZCalendarWeekView/JZBaseWeekView.swift index a852e8c..2edb690 100644 --- a/JZCalendarWeekView/JZBaseWeekView.swift +++ b/JZCalendarWeekView/JZBaseWeekView.swift @@ -31,7 +31,7 @@ open class JZBaseWeekView: UIView { (numOfDays) days before current page first date, which means the start of the collectionView, not the current page first date - The core structure of JZCalendarWeekView is 3 pages, previous-current-next - If you want to update this value instead of using [updateWeekView(to date: Date)](), please **make sure the date is startOfDay**. - */ + */ public var initDate: Date! { didSet { baseDelegate?.initDateDidChange(self, initDate: initDate) @@ -144,17 +144,17 @@ open class JZBaseWeekView: UIView { /** Basic Setup method for JZCalendarWeekView,it **must** be called. - + - Parameters: - - numOfDays: Number of days in a page - - setDate: The initial set date, the first date in current page except WeekView (numOfDays = 7) - - allEvents: The dictionary of all the events for present. JZWeekViewHelper.getIntraEventsByDate can help transform the data - - firstDayOfWeek: First day of a week, **only works when numOfDays is 7**. Default value is Sunday - - scrollType: The horizontal scroll type for this view. Default value is pageScroll - - currentTimelineType: The current time line type for this view. Default value is section - - visibleTime: WeekView will be scroll to this time, when it appears the **first time**. This visibleTime only determines **y** offset. Defaut value is current time. - - scrollableRange: The scrollable area for this weekView, both start and end dates are included, set nil as unlimited in one side - */ + - numOfDays: Number of days in a page + - setDate: The initial set date, the first date in current page except WeekView (numOfDays = 7) + - allEvents: The dictionary of all the events for present. JZWeekViewHelper.getIntraEventsByDate can help transform the data + - firstDayOfWeek: First day of a week, **only works when numOfDays is 7**. Default value is Sunday + - scrollType: The horizontal scroll type for this view. Default value is pageScroll + - currentTimelineType: The current time line type for this view. Default value is section + - visibleTime: WeekView will be scroll to this time, when it appears the **first time**. This visibleTime only determines **y** offset. Defaut value is current time. + - scrollableRange: The scrollable area for this weekView, both start and end dates are included, set nil as unlimited in one side + */ open func setupCalendar(numOfDays: Int, setDate: Date, allEvents: [Date: [JZBaseEvent]], @@ -330,11 +330,15 @@ open class JZBaseWeekView: UIView { return dates } + open func selectedItemAt(indexPath: IndexPath) { + + } + /** - Used to Refresh the weekView when viewWillTransition - - **Must override viewWillTransition in the ViewController and call this function** - */ + Used to Refresh the weekView when viewWillTransition + + **Must override viewWillTransition in the ViewController and call this function** + */ open func refreshWeekView() { updateWeekView(to: self.initDate.add(component: .day, value: numOfDays)) } @@ -358,7 +362,7 @@ open class JZBaseWeekView: UIView { /** Get date excluding time from **collectionView contentOffset only** rather than gesture point in collectionView - - Parameter contentOffsetX: collectionView contentOffset x + - Parameter contentOffsetX: collectionView contentOffset x */ open func getDateForContentOffsetX(_ contentOffsetX: CGFloat) -> Date { let adjustedX = contentOffsetX - flowLayout.contentsMargin.left @@ -368,7 +372,7 @@ open class JZBaseWeekView: UIView { /** Get time excluding date from **collectionView contentOffset only** rather than gesture point in collectionView - - Parameter contentOffsetY: collectionView contentOffset y + - Parameter contentOffsetY: collectionView contentOffset y */ open func getDateForContentOffsetY(_ contentOffsetY: CGFloat) -> (hour: Int, minute: Int) { var adjustedY = contentOffsetY - flowLayout.contentsMargin.top @@ -380,7 +384,7 @@ open class JZBaseWeekView: UIView { /** Get full date from **collectionView contentOffset only** rather than gesture point in collectionView - - Parameter contentOffset: collectionView contentOffset + - Parameter contentOffset: collectionView contentOffset */ open func getDateForContentOffset(_ contentOffset: CGPoint) -> Date { let yearMonthDay = getDateForContentOffsetX(contentOffset.x) @@ -390,7 +394,7 @@ open class JZBaseWeekView: UIView { /** Get date excluding time from **gesture point in collectionView only** rather than collectionView contentOffset - - Parameter xCollectionView: gesture point x in collectionView + - Parameter xCollectionView: gesture point x in collectionView */ open func getDateForPointX(_ xCollectionView: CGFloat) -> Date { // RowHeader(horizontal UICollectionReusableView) should be considered in gesture point @@ -402,7 +406,7 @@ open class JZBaseWeekView: UIView { /** Get time excluding date from **gesture point in collectionView only** rather than collectionView contentOffset - - Parameter yCollectionView: gesture point y in collectionView + - Parameter yCollectionView: gesture point y in collectionView */ open func getDateForPointY(_ yCollectionView: CGFloat) -> (hour: Int, minute: Int) { // ColumnHeader and AllDayHeader(vertical UICollectionReusableView) should be considered in gesture point @@ -418,7 +422,7 @@ open class JZBaseWeekView: UIView { /** Get full date from **gesture point in collectionView only** rather than collectionView contentOffset - - Parameter point: gesture point in collectionView + - Parameter point: gesture point in collectionView */ open func getDateForPoint(_ point: CGPoint) -> Date { let yearMonthDay = getDateForPointX(point.x) @@ -529,6 +533,10 @@ extension JZBaseWeekView: UICollectionViewDelegate, UICollectionViewDelegateFlow self.endOfScroll() } + open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + self.selectedItemAt(indexPath: indexPath) + } + /// Some actions need to be done when scroll ends private func endOfScroll() { // vertical scroll should not load page, handled in loadPage method diff --git a/JZCalendarWeekView/JZLongPressWeekView.swift b/JZCalendarWeekView/JZLongPressWeekView.swift index 7c75c30..0170914 100644 --- a/JZCalendarWeekView/JZLongPressWeekView.swift +++ b/JZCalendarWeekView/JZLongPressWeekView.swift @@ -25,6 +25,13 @@ public protocol JZLongPressViewDelegate: class { /// - startDate: the startDate of the event when gesture ends func weekView(_ weekView: JZLongPressWeekView, editingEvent: JZBaseEvent, didEndMoveLongPressAt startDate: Date) + /// When Custom long press gesture begins on an , this function will be called. + /// Use this function to perform actions when a use long presses on an existing event + /// - Parameters: + /// - weekView: current long pressed JZLongPressWeekView + /// - cell: current long pressed JZLongPressEventCell + func weekView(_ weekView: JZLongPressWeekView, didBeginLongPressOn cell: JZLongPressEventCell) + /// Sometimes the longPress will be cancelled because some curtain reason. /// Normally this function no need to be implemented. /// - Parameters: @@ -57,6 +64,7 @@ extension JZLongPressViewDelegate { public func weekView(_ weekView: JZLongPressWeekView, longPressType: JZLongPressWeekView.LongPressType, didCancelLongPressAt startDate: Date) {} public func weekView(_ weekView: JZLongPressWeekView, didEndAddNewLongPressAt startDate: Date) {} public func weekView(_ weekView: JZLongPressWeekView, editingEvent: JZBaseEvent, didEndMoveLongPressAt startDate: Date) {} + public func weekView(_ weekView: JZLongPressWeekView, didBeginLongPressOn cell: JZLongPressEventCell) {} } extension JZLongPressViewDataSource { @@ -78,6 +86,8 @@ open class JZLongPressWeekView: JZBaseWeekView { case addNew /// when long press position is on a existed event, this type will allow user to move the existed event case move + // Custom event to implement functionality besides move when long press on an existing event + case custom } /// This structure is used to save editing information before reusing collectionViewCell (Type Move used only) @@ -271,7 +281,7 @@ open class JZLongPressWeekView: JZBaseWeekView { open func initLongPressView(selectedCell: UICollectionViewCell?, type: LongPressType, startDate: Date) -> UIView { let longPressView = type == .move ? longPressDataSource!.weekView(self, movingCell: selectedCell!, viewForMoveLongPressAt: startDate) : - longPressDataSource!.weekView(self, viewForAddNewLongPressAt: startDate) + longPressDataSource!.weekView(self, viewForAddNewLongPressAt: startDate) longPressView.clipsToBounds = false // timeText width will change from 00:00 - 24:00, and for each time the length will be different @@ -371,12 +381,16 @@ extension JZLongPressWeekView: UIGestureRecognizerDelegate { if gestureRecognizer.state == .possible { // Long press on ouside margin area should not begin let isOutsideBeginArea = pointInSelfView.x < longPressLeftMarginX || pointInSelfView.x > longPressRightMarginX || - pointInSelfView.y < longPressTopMarginY || pointInSelfView.y > longPressBottomMarginY + pointInSelfView.y < longPressTopMarginY || pointInSelfView.y > longPressBottomMarginY if isOutsideBeginArea { return false } } let hasItemAtPoint = collectionView.indexPathForItem(at: pointInCollectionView) != nil + if hasItemAtPoint && longPressTypes.contains(LongPressType.custom) { + return true + } + // Long press should not begin if there are events at long press position and move not required if hasItemAtPoint && !longPressTypes.contains(LongPressType.move) { return false @@ -400,19 +414,37 @@ extension JZLongPressWeekView: UIGestureRecognizerDelegate { let pointInCollectionView = gestureRecognizer.location(in: collectionView) let state = gestureRecognizer.state - var currentMovingCell: UICollectionViewCell! + + var currentLongPressCell: UICollectionViewCell! if isLongPressing == false { if let indexPath = collectionView.indexPathForItem(at: pointInCollectionView) { // Can add some conditions for allowing only few types of cells can be moved - currentLongPressType = .move - currentMovingCell = collectionView.cellForItem(at: indexPath) + if longPressTypes.contains(.move) { + currentLongPressType = .move + currentLongPressCell = collectionView.cellForItem(at: indexPath) + } else if longPressTypes.contains(.custom) { + currentLongPressType = .custom + currentLongPressCell = collectionView.cellForItem(at: indexPath) + } } else { currentLongPressType = .addNew } isLongPressing = true } + if currentLongPressType == .custom { + if state == .began { + longPressDelegate?.weekView(self, didBeginLongPressOn: currentLongPressCell as! JZLongPressEventCell) + return + } else if state == .ended || state == .cancelled { + isLongPressing = false + return + } else { + return + } + } + // The startDate of the longPressView (the date of top Y in longPressView) var longPressViewStartDate: Date! @@ -422,20 +454,20 @@ extension JZLongPressWeekView: UIGestureRecognizerDelegate { } if state == .began { + currentEditingInfo.cellSize = currentLongPressType == .move ? currentLongPressCell.frame.size : CGSize(width: flowLayout.sectionWidth, height: flowLayout.hourHeight * CGFloat(addNewDurationMins)/60) + pressPosition = currentLongPressType == .move ? (pointInCollectionView.x - currentLongPressCell.frame.origin.x, pointInCollectionView.y - currentLongPressCell.frame.origin.y) : (currentEditingInfo.cellSize.width/2, currentEditingInfo.cellSize.height/2) - currentEditingInfo.cellSize = currentLongPressType == .move ? currentMovingCell.frame.size : CGSize(width: flowLayout.sectionWidth, height: flowLayout.hourHeight * CGFloat(addNewDurationMins)/60) - pressPosition = currentLongPressType == .move ? (pointInCollectionView.x - currentMovingCell.frame.origin.x, pointInCollectionView.y - currentMovingCell.frame.origin.y) : - (currentEditingInfo.cellSize.width/2, currentEditingInfo.cellSize.height/2) longPressViewStartDate = getLongPressViewStartDate(pointInCollectionView: pointInCollectionView, pointInSelfView: pointInSelfView) - longPressView = initLongPressView(selectedCell: currentMovingCell, type: currentLongPressType, startDate: longPressViewStartDate) + longPressView = initLongPressView(selectedCell: currentLongPressCell, type: currentLongPressType, startDate: longPressViewStartDate) longPressView.frame.size = currentEditingInfo.cellSize longPressView.transform = CGAffineTransform(scaleX: 0.1, y: 0.1) self.addSubview(longPressView) longPressView.center = CGPoint(x: pointInSelfView.x - pressPosition!.xToViewLeft + currentEditingInfo.cellSize.width/2, y: pointInSelfView.y - pressPosition!.yToViewTop + currentEditingInfo.cellSize.height/2) + if currentLongPressType == .move { - currentEditingInfo.event = (currentMovingCell as! JZLongPressEventCell).event + currentEditingInfo.event = (currentLongPressCell as! JZLongPressEventCell).event getCurrentMovingCells().forEach { $0.contentView.layer.opacity = movingCellOpacity currentEditingInfo.allOpacityContentViews.append($0.contentView) @@ -449,18 +481,14 @@ extension JZLongPressWeekView: UIGestureRecognizerDelegate { let topYPoint = max(pointInSelfView.y - pressPosition!.yToViewTop, longPressTopMarginY) longPressView.center = CGPoint(x: pointInSelfView.x - pressPosition!.xToViewLeft + currentEditingInfo.cellSize.width/2, y: topYPoint + currentEditingInfo.cellSize.height/2) - } else if state == .cancelled { - UIView.animate(withDuration: 0.3, delay: 0.0, options: .curveEaseOut, animations: { self.longPressView.alpha = 0 }, completion: { _ in self.longPressView.removeFromSuperview() }) longPressDelegate?.weekView(self, longPressType: currentLongPressType, didCancelLongPressAt: longPressViewStartDate) - } else if state == .ended { - self.longPressView.removeFromSuperview() if currentLongPressType == .addNew { longPressDelegate?.weekView(self, didEndAddNewLongPressAt: longPressViewStartDate) diff --git a/JZCalendarWeekView/JZWeekViewFlowLayout.swift b/JZCalendarWeekView/JZWeekViewFlowLayout.swift index d6c933b..8cfdefc 100644 --- a/JZCalendarWeekView/JZWeekViewFlowLayout.swift +++ b/JZCalendarWeekView/JZWeekViewFlowLayout.swift @@ -44,7 +44,6 @@ open class JZWeekViewFlowLayout: UICollectionViewFlowLayout { let height = hourHeight * 24 // statement too long for Swift 5 compiler return columnHeaderHeight + height + contentsMargin.top + contentsMargin.bottom + allDayHeaderHeight } - let minOverlayZ = 1000 // Allows for 900 items in a section without z overlap issues let minCellZ = 100 // Allows for 100 items in a section's background let minBackgroundZ = 0 diff --git a/README.md b/README.md index 91d9c15..838a2c4 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,8 @@ public protocol JZLongPressViewDelegate: class { 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) + /// When an event is long pressed on, this function will be called. + func weekView(_ weekView: JZLongPressWeekView, didBeginLongPressOn cell: JZLongPressEventCell) /// Sometimes the longPress will be cancelled because some curtain reason. func weekView(_ weekView: JZLongPressWeekView, longPressType: JZLongPressWeekView.LongPressType, didCancelLongPressAt startDate: Date) } @@ -110,10 +112,10 @@ public protocol JZLongPressViewDataSource: class { ``` Also, you should provide the long press types and there are some other properties you can change. -```swift +```swift calendarWeekView.longPressDelegate = self calendarWeekView.longPressDataSource = self -calendarWeekView.longPressTypes = [.addNew, .move] +calendarWeekView.longPressTypes = [.addNew, .move, .custom] // Optional calendarWeekView.addNewDurationMins = 120 @@ -126,7 +128,7 @@ If you want to use the `move` type long press, you have to inherit your `UIColle 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. -```swift +```swift open class func getIntraEventsByDate(originalEvents: [T]) -> [Date: [T]] ``` In order to call this function, you should create a subclass of `JZBaseEvent` and also implement the `NSCopying` protocol.
@@ -192,6 +194,3 @@ If you have any questions and suggestions, feel free to contact me. ## License JZCalendarWeekView is available under the MIT license. See the [LICENSE](https://github.com/zjfjack/JZCalendarWeekView/blob/master/LICENSE) for more info. - - -