From 2f741ebaab07e47d817eb0883fdceaf0ecf6aa3a Mon Sep 17 00:00:00 2001 From: Till Hellmund Date: Sun, 25 Nov 2018 19:42:02 +0100 Subject: [PATCH] Fix issue where tapping multi-day events lead to a crash, minor other code improvements --- .../com/alamkanak/weekview/DateUtils.java | 29 +++-- .../com/alamkanak/weekview/WeekViewEvent.java | 102 ++++++++++-------- .../sample/database/FakeEventsDatabase.java | 15 +++ 3 files changed, 85 insertions(+), 61 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/DateUtils.java b/library/src/main/java/com/alamkanak/weekview/DateUtils.java index 7c92add70..1c571c79c 100644 --- a/library/src/main/java/com/alamkanak/weekview/DateUtils.java +++ b/library/src/main/java/com/alamkanak/weekview/DateUtils.java @@ -30,19 +30,21 @@ static List getDateRange(int daysSinceToday, int size) { } static Calendar withTimeAtStartOfDay(Calendar date) { - date.set(Calendar.HOUR_OF_DAY, 0); - date.set(Calendar.MINUTE, 0); - date.set(Calendar.SECOND, 0); - date.set(Calendar.MILLISECOND, 0); - return date; + Calendar newDate = (Calendar) date.clone(); + newDate.set(Calendar.HOUR_OF_DAY, 0); + newDate.set(Calendar.MINUTE, 0); + newDate.set(Calendar.SECOND, 0); + newDate.set(Calendar.MILLISECOND, 0); + return newDate; } static Calendar withTimeAtEndOfDay(Calendar date) { - date.set(Calendar.HOUR_OF_DAY, 23); - date.set(Calendar.MINUTE, 59); - date.set(Calendar.SECOND, 59); - date.set(Calendar.MILLISECOND, 999); - return date; + Calendar newDate = (Calendar) date.clone(); + newDate.set(Calendar.HOUR_OF_DAY, 23); + newDate.set(Calendar.MINUTE, 59); + newDate.set(Calendar.SECOND, 59); + newDate.set(Calendar.MILLISECOND, 999); + return newDate; } static int getDaysUntilDate(Calendar date) { @@ -71,11 +73,8 @@ static boolean isSameDay(Calendar dayOne, Calendar dayTwo) { * @param date2 The second date * @return Whether or not date2 is at the start of the day after date1 */ - public static boolean isAtStartOfNewDay(Calendar date1, Calendar date2){ - if(date2.get(Calendar.HOUR) == 0 && - date2.get(Calendar.MINUTE) == 0 && - date2.get(Calendar.SECOND) == 0 && - date2.get(Calendar.MILLISECOND) == 0){ + static boolean isAtStartOfNewDay(Calendar date1, Calendar date2) { + if (date2 == withTimeAtStartOfDay(date2)) { date2.add(Calendar.MILLISECOND, -1); return isSameDay(date1, date2); } diff --git a/library/src/main/java/com/alamkanak/weekview/WeekViewEvent.java b/library/src/main/java/com/alamkanak/weekview/WeekViewEvent.java index 331a1aadb..605a9d0d0 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekViewEvent.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekViewEvent.java @@ -7,6 +7,9 @@ import java.util.Calendar; import java.util.List; +import static com.alamkanak.weekview.DateUtils.isAtStartOfNewDay; +import static com.alamkanak.weekview.DateUtils.withTimeAtEndOfDay; + /** * Created by Raquib-ul-Alam Kanak on 7/21/2014. * Website: http://april-shower.com @@ -198,63 +201,70 @@ public int hashCode() { List> splitWeekViewEvents() { List> events = new ArrayList<>(); - // Clone this endtime for when we need to clone events - Calendar clonedEndTime = (Calendar) this.endTime.clone(); - - if(DateUtils.isAtStartOfNewDay(this.getStartTime(), clonedEndTime)) { - // Set end time to 1 minute before midnight to ensure the EventRect will get drawn correctly - clonedEndTime.set(Calendar.HOUR_OF_DAY, 23); - clonedEndTime.set(Calendar.MINUTE, 59); - WeekViewEvent event1 = new WeekViewEvent<>(id, title, startTime, clonedEndTime, location, isAllDay); - event1.setColor(this.getColor()); - events.add(event1); - }else if (!isSameDay(clonedEndTime)) { - clonedEndTime = (Calendar) startTime.clone(); - clonedEndTime.set(Calendar.HOUR_OF_DAY, 23); - clonedEndTime.set(Calendar.MINUTE, 59); - - WeekViewEvent event1 = new WeekViewEvent<>(id, title, startTime, clonedEndTime, location, isAllDay); - event1.setColor(color); - events.add(event1); - - // Add other days. - Calendar otherDay = (Calendar) startTime.clone(); - otherDay.add(Calendar.DATE, 1); + // Clone this end time for when we need to clone events + Calendar newEndTime = (Calendar) this.endTime.clone(); - while (!DateUtils.isSameDay(otherDay, this.endTime)) { - Calendar overDay = (Calendar) otherDay.clone(); - overDay.set(Calendar.HOUR_OF_DAY, 0); - overDay.set(Calendar.MINUTE, 0); + if (isAtStartOfNewDay(startTime, newEndTime)) { + // Set end time to 1ms before midnight to ensure the EventRect will get drawn correctly + WeekViewEvent shortenedEvent = shortenTooLongAllDayEvent(newEndTime); + events.add(shortenedEvent); + } else if (!isSameDay(newEndTime)) { + events = splitEventByDays(newEndTime); + } else { + events.add(this); + } - Calendar endOfOverDay = (Calendar) overDay.clone(); - endOfOverDay.set(Calendar.HOUR_OF_DAY, 23); - endOfOverDay.set(Calendar.MINUTE, 59); + return events; + } - WeekViewEvent eventMore = new WeekViewEvent<>(id, title, overDay, endOfOverDay, location, isAllDay); - eventMore.setColor(color); - events.add(eventMore); + private WeekViewEvent shortenTooLongAllDayEvent(Calendar newEndTime) { + return new WeekViewEvent<>(id, title, startTime, + withTimeAtEndOfDay(newEndTime), location, color, isAllDay, data); + } - // Add next day. - otherDay.add(Calendar.DATE, 1); - } + private List> splitEventByDays(Calendar newEndTime) { + List> results = new ArrayList<>(); + newEndTime = withTimeAtEndOfDay(newEndTime); - // Add last day. - Calendar startTime = (Calendar) this.endTime.clone(); - startTime.set(Calendar.HOUR_OF_DAY, 0); - startTime.set(Calendar.MINUTE, 0); + WeekViewEvent event1 = new WeekViewEvent<>(id, title, + startTime, newEndTime, location, color, isAllDay, data); + results.add(event1); - WeekViewEvent event2 = new WeekViewEvent<>(id, title, startTime, this.endTime, location, isAllDay); - event2.setColor(color); - events.add(event2); - } else { - events.add(this); + // Add other days. + Calendar otherDay = (Calendar) startTime.clone(); + otherDay.add(Calendar.DATE, 1); + + while (!DateUtils.isSameDay(otherDay, this.endTime)) { + Calendar overDay = (Calendar) otherDay.clone(); + overDay.set(Calendar.HOUR_OF_DAY, 0); + overDay.set(Calendar.MINUTE, 0); + + Calendar endOfOverDay = (Calendar) overDay.clone(); + endOfOverDay.set(Calendar.HOUR_OF_DAY, 23); + endOfOverDay.set(Calendar.MINUTE, 59); + + WeekViewEvent eventMore = new WeekViewEvent<>(id, title, + overDay, endOfOverDay, location, color, isAllDay, data); + results.add(eventMore); + + // Add next day. + otherDay.add(Calendar.DATE, 1); } - return events; + // Add last day. + Calendar startTime = (Calendar) this.endTime.clone(); + startTime.set(Calendar.HOUR_OF_DAY, 0); + startTime.set(Calendar.MINUTE, 0); + + WeekViewEvent event2 = new WeekViewEvent<>(id, title, + startTime, this.endTime, location, color, isAllDay, data); + results.add(event2); + + return results; } @Override - public WeekViewEvent toWeekViewEvent() { + public WeekViewEvent toWeekViewEvent() { return this; } diff --git a/sample/src/main/java/com/alamkanak/weekview/sample/database/FakeEventsDatabase.java b/sample/src/main/java/com/alamkanak/weekview/sample/database/FakeEventsDatabase.java index 5c932d7f4..a46716b41 100644 --- a/sample/src/main/java/com/alamkanak/weekview/sample/database/FakeEventsDatabase.java +++ b/sample/src/main/java/com/alamkanak/weekview/sample/database/FakeEventsDatabase.java @@ -44,6 +44,21 @@ public List> getEventsInRange(Calendar startDate, Cal event = new Event(1, getEventTitle(startTime), startTime, endTime, null, color1, false); events.add(event); + // Add multi-day event + startTime = Calendar.getInstance(); + startTime.set(Calendar.HOUR_OF_DAY, 3); + startTime.set(Calendar.MINUTE, 30); + startTime.set(Calendar.MONTH, newMonth-1); + startTime.set(Calendar.YEAR, newYear); + endTime = (Calendar) startTime.clone(); + endTime.add(Calendar.DAY_OF_MONTH, 2); + endTime.set(Calendar.HOUR_OF_DAY, 4); + endTime.set(Calendar.MINUTE, 30); + endTime.set(Calendar.MONTH, newMonth-1); + + event = new Event(123, getEventTitle(startTime), startTime, endTime, null, color4, false); + events.add(event); + startTime = Calendar.getInstance(); startTime.set(Calendar.HOUR_OF_DAY, 3); startTime.set(Calendar.MINUTE, 30);