Visible scrolling when trying to start calendar at a certain date #263
(Required) Version Number: JTAppleCalendar 8.0.2
Description
Absolutely love JTAppleCalendar. Using it in production apps for about two years now. But, I recently ran into an issue. I am having the same issue as Issue #263.
I want the calendar to be on a selected date when it first appears, so I do calendarView.scrollToDate(selectedDate) at viewDidLoad().
When I go to the calendar's view controller, I can see the starting month flash very quickly, and then the selected month shows up (even if I use animateScroll = false). This is very quick in the simulator, but very apparent on my iPhone 6 (running iOS 12.4.9). For example, you can clearly see September 2020 show up before the calendar changes over to show January 2021.
Steps To Reproduce
Here is my code:
let startDate = Date(timeIntervalSince1970: FamilyData.setupCompletedDate)
let endDate = Date()
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
}
// ---------------
// Collection View
// ---------------
func configureCalendar(_ calendar: JTACMonthView) -> ConfigurationParameters {
// These are the dates the user can select from when choosing due dates
// end date will always be at the end of their budget period
// start date depends on which calendar they're looking at.
// If they're looking at the first payment calendar, then the first selectable date should be the first day of their budget
// BUT... if they're looking at the last payment calendar, then the first selectable date should be AFTER the first due date
return ConfigurationParameters(startDate: startDate,
endDate: endDate,
calendar: FamilyData.calendar(),
generateInDates: .forAllMonths,
generateOutDates: .tillEndOfRow)
}
func configureCell(view: JTACDayCell?, cellState: CellState) {
guard let cell = view as? DateCell else { return }
cell.dateLabel.text = cellState.text
handleCellTextColor(cell: cell,
cellState: cellState)
handleCellSelected(cell: cell,
cellState: cellState)
}
func handleCellSelected(cell: DateCell, cellState: CellState) {
// round corner of BG, whether it's showing or not
cell.selectedView.layer.cornerRadius = cell.selectedView.layer.bounds.height / 2
if cellState.date < startDate || cellState.date > endDate {
cell.dateLabel.textColor = .mpGray40
cell.selectedView.isHidden = true
cell.isUserInteractionEnabled = false
} else if cellState.isSelected {
cell.dateLabel.textColor = .white
cell.selectedView.backgroundColor = .mpBlue
cell.selectedView.isHidden = false
cell.isUserInteractionEnabled = true
} else {
cell.dateLabel.textColor = .black
cell.selectedView.isHidden = true
cell.isUserInteractionEnabled = true
}
if FamilyData.calendar().isDate(cellState.date, inSameDayAs: Date()) {
if !cellState.isSelected {
cell.dateLabel.textColor = .mpBlue
cell.selectedView.isHidden = true
}
}
}
func handleCellTextColor(cell: DateCell, cellState: CellState) {
if cellState.dateBelongsTo == .thisMonth {
cell.isHidden = false
} else {
cell.isHidden = true
}
}
func calendar(_ calendar: JTACMonthView, cellForItemAt date: Date, cellState: CellState, indexPath: IndexPath) -> JTACDayCell {
let cell = calendar.dequeueReusableJTAppleCell(withReuseIdentifier: "dateCell", for: indexPath) as! DateCell
self.calendar(calendar,
willDisplay: cell,
forItemAt: date,
cellState: cellState,
indexPath: indexPath)
return cell
}
func calendar(_ calendar: JTACMonthView, willDisplay cell: JTACDayCell, forItemAt date: Date, cellState: CellState, indexPath: IndexPath) {
configureCell(view: cell,
cellState: cellState)
}
func calendar(_ calendar: JTACMonthView, headerViewForDateRange range: (start: Date, end: Date), at indexPath: IndexPath) -> JTACMonthReusableView {
let header = calendar.dequeueReusableJTAppleSupplementaryView(withReuseIdentifier: "DateHeader", for: indexPath) as! DateHeader
header.monthTitle.text = DateFormatter().mpMonth(from: range.start)
return header
}
func calendarSizeForMonths(_ calendar: JTACMonthView?) -> MonthSize? {
return MonthSize(defaultSize: 50)
}
func calendar(_ calendar: JTACMonthView, didSelectDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath) {
configureCell(view: cell,
cellState: cellState)
// When a user selects a day, they get the start of day but not the time.
// So, we'll transpose the current day's time onto the selected day.
// This will ensure unique dates for transactions.
let dateOffset = date.days(from: Date())
selectedDate = FamilyData.calendar().date(byAdding: .day, value: dateOffset, to: Date())!
calendar.reloadData()
}
func calendar(_ calendar: JTACMonthView, didDeselectDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath) {
configureCell(view: cell,
cellState: cellState)
}
// ---------
// Functions
// ---------
func setupUI() {
// Calendar views
calendarView.ibCalendarDelegate = self
calendarView.ibCalendarDataSource = self
calendarView.scrollDirection = .horizontal
calendarView.scrollingMode = .nonStopToSection(withResistance: 0.5)
calendarView.showsHorizontalScrollIndicator = false
// If user already had a date selected and is returning to calendar picker, then automatically scroll to their selected date
// Otherwise, default is today
calendarView.scrollToDate(selectedDate, animateScroll: false)
calendarView.selectDates([selectedDate])
}`
Expected Behavior
As you can see, my code is pretty boilerplate. Not a whole lot of customization going on. But when I load the view, I expect it to go right to the selected date, not flash the initial month first.
Additional Context
I've tried putting the scrollToDate code in viewWillAppear as well as viewDidLayoutSubviews, but to no avail. I'm using Xcode 11.3.1, if that helps.
Thanks for your support. Will have to take a look over the weekend. I'm a little tied up on work
Thanks!!
On Thu, Jan 14, 2021 at 3:34 PM PatchTheCode [email protected] wrote:
Thanks for your support. Will have to take a look over the weekend.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/patchthecode/JTAppleCalendar/issues/1304#issuecomment-760545106, or unsubscribe https://github.com/notifications/unsubscribe-auth/AHD5UIGMELHUNNJ72YMRM43SZ55RZANCNFSM4WAOI6BQ .
Hi. Any progress on this?
I'm experiencing the same on 2024 which is a bit disappointing
@vitaliichernysh i think the fastest way to heklp me resolve this is to provide a minimal app which recreates this issue.
Edge case bugs are very hard to find based on code. Often, its one tiny setting based on your app. So can you please provide an empty app for me which recreates this issue? No, extra designs or company codes etc. Just a minimal calendar that recreates this issue.