kovpas/PMCalendar

Setting Calendar Period Renders Rows Incorrectly

Closed this issue · 6 comments

I am still trying to get to the bottom of this and the behavior doesn't seem to happen within the PMCalendar example app, but I am seeing a behavior in which the configuration of the period with a one-day selected period (i.e. self.calendarController.period = [PMPeriod oneDayPeriodWithDate:self.selectedDate];) results in the incorrect rendering of the day cells in the last week of the month. The cells seem to draw at about half-height. Not configuring the period results in appropriate rendering.

I am on latest master version (ref 98802aa)

We have a custom calendar theme, but the behavior also occurs when I use one of the bundled themes. We are also presenting the calendar from a rect in a view with isPopover:NO.

See the screenshots for examples:

With current period configured:
iOS SimulatorScreenSnapz064

Without:
simulator

Could you please attach some code, as I've tried to reproduce this in a demo app and indeed it works fine.

self.pmCC.period = [PMPeriod oneDayPeriodWithDate:[[NSDate date] dateByAddingDays:10]];

Yeah sure, here's the initialization:

self.calendarController = [[PMCalendarController alloc] initWithThemeName:@"calendar" andSize:CGSizeMake(320, 370)];
self.calendarController.delegate = self;
self.calendarController.allowsPeriodSelection = NO;
self.calendarController.allowsLongPressMonthChange = YES;
self.calendarController.period = [PMPeriod oneDayPeriodWithDate:self.selectedDate];

NSDate *midnightYesterday = [[NSDate date] dateByAddingDays:-1];
NSDate *oneYearFromToday = [[NSDate date] dateByAddingYears:1];
self.calendarController.allowedPeriod = [PMPeriod periodWithStartDate:midnightYesterday endDate:oneYearFromToday];

[self.calendarController presentCalendarFromRect:CGRectMake(0, -360, 320, 370)
                                          inView:self.view
                        permittedArrowDirections:PMCalendarArrowDirectionAny
                                       isPopover:NO
                                        animated:NO];

Note that I have to use a big ass negative Y index to get the calendar to render within the bounds of the presenting view. This behavior appeared after I rebased yesterday against master after being on a branch for months.

So I have been tracing this through and it looks like what is happening is that the call to presentCalendarFromRect:inView: permittedArrowDirections:isPopover:animated: is causing the initialFrame and size properties of the Calendar to be mutated after initialization.

In my case, this is moving the size from (320, 370) to (320, 335), which causes all subsequent rendering to be truncated as the rects array specifies origin points that draw beyond the bounds.

In particular it is these lines where things go sideways:

CGRect rectInAppWindow = [self.view convertRect:rect fromView:view];
[self adjustCalendarPositionForPermittedArrowDirections:arrowDirections
                                      arrowPointsToRect:rectInAppWindow];
self.initialFrame = self.mainView.frame;
[self fullRedraw];

Yes, it's mutated in order to cut unused calendar dates. I.e. if you show calendar for Feb 2013, there should be 5 lines, not 6. What is weird on attached screenshots is that it shows all 6 lines. Can't really say why this happens, as I still can't reproduce the problem. Could you please modify demo project's code so the problem appears there?

So we are using a fixed grid background that always shows 6 rows. I have managed to fix the problem by maintaining a new ivar called initialSize and then using that property to compute the initialFrame, thus ensuring that the frame matches the size constraints specified when you init with an explicit size:

    CGRect rectInAppWindow = [self.view convertRect:rect fromView:view];
    [self adjustCalendarPositionForPermittedArrowDirections:arrowDirections
                                          arrowPointsToRect:rectInAppWindow];
    self.initialFrame = CGRectMake(self.mainView.frame.origin.x, self.mainView.frame.origin.y, self.initialSize.width, self.initialSize.height);
    [self fullRedraw];