From 8f351647c9206317c1e8b615ec6789bcf6c0a1ff Mon Sep 17 00:00:00 2001 From: Badrinarayan Vijayakumar Date: Mon, 26 Nov 2018 18:13:06 -0500 Subject: [PATCH] Implementation of Two Week display mode --- .../materialcalendarview/CalendarMode.java | 6 +- .../MaterialCalendarView.java | 14 ++++ .../TwoWeekPagerAdapter.java | 80 +++++++++++++++++++ .../materialcalendarview/TwoWeekView.java | 41 ++++++++++ library/src/main/res/values/attrs.xml | 1 + .../BiWeeklyRangeIndexTest.java | 45 +++++++++++ .../sample/DynamicSettersActivity.java | 8 ++ .../SwappableBasicActivityDecorated.java | 7 ++ .../main/res/layout/activity_basic_modes.xml | 41 ++++++---- .../res/layout/activity_dynamic_setters.xml | 46 ++++++----- 10 files changed, 252 insertions(+), 37 deletions(-) create mode 100644 library/src/main/java/com/prolificinteractive/materialcalendarview/TwoWeekPagerAdapter.java create mode 100644 library/src/main/java/com/prolificinteractive/materialcalendarview/TwoWeekView.java create mode 100644 library/src/test/java/com/prolificinteractive/materialcalendarview/BiWeeklyRangeIndexTest.java diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarMode.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarMode.java index 3c704ad8..42fabb5f 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarMode.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarMode.java @@ -12,7 +12,11 @@ public enum CalendarMode { /** * Week mode that shows the calendar week by week. */ - WEEKS(1); + WEEKS(1), + /** + * Two Week mode that shows the calendar in two weeks. + */ + TWO_WEEKS(2); /** * Number of visible weeks per calendar mode. diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/MaterialCalendarView.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/MaterialCalendarView.java index 6205f2a5..bdbc428d 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/MaterialCalendarView.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/MaterialCalendarView.java @@ -1946,6 +1946,17 @@ private void commit(State state) { } else { calendarDayToShow = lastVisibleCalendarDay; } + } else if (calendarMode == CalendarMode.TWO_WEEKS) { + LocalDate lastVisibleCalendar = calendarDayToShow.getDate(); + CalendarDay lastVisibleCalendarDay = CalendarDay.from(lastVisibleCalendar.plusDays(13)); + if (currentlySelectedDate != null && + (currentlySelectedDate.equals(calendarDayToShow) || currentlySelectedDate.equals(lastVisibleCalendarDay) || + (currentlySelectedDate.isAfter(calendarDayToShow) && currentlySelectedDate.isBefore(lastVisibleCalendarDay)))) { + // Currently selected date is within view, so center on that + calendarDayToShow = currentlySelectedDate; + } else { + calendarDayToShow = lastVisibleCalendarDay; + } } } } @@ -1967,6 +1978,9 @@ private void commit(State state) { case WEEKS: newAdapter = new WeekPagerAdapter(this); break; + case TWO_WEEKS: + newAdapter = new TwoWeekPagerAdapter(this); + break; default: throw new IllegalArgumentException("Provided display mode which is not yet implemented"); } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/TwoWeekPagerAdapter.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/TwoWeekPagerAdapter.java new file mode 100644 index 00000000..2554e0d8 --- /dev/null +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/TwoWeekPagerAdapter.java @@ -0,0 +1,80 @@ +package com.prolificinteractive.materialcalendarview; + +import android.support.annotation.NonNull; + +import org.threeten.bp.DayOfWeek; +import org.threeten.bp.LocalDate; +import org.threeten.bp.jdk8.Jdk8Methods; +import org.threeten.bp.temporal.ChronoUnit; +import org.threeten.bp.temporal.WeekFields; + +public class TwoWeekPagerAdapter extends CalendarPagerAdapter { + + public TwoWeekPagerAdapter(MaterialCalendarView mcv) { + super(mcv); + } + + @Override + protected TwoWeekView createView(int position) { + return new TwoWeekView(mcv, getItem(position), mcv.getFirstDayOfWeek(), showWeekDays); + } + + @Override + protected int indexOf(TwoWeekView view) { + CalendarDay week = view.getFirstViewDay(); + return getRangeIndex().indexOf(week); + } + + @Override + protected boolean isInstanceOfView(Object object) { + return object instanceof TwoWeekView; + } + + @Override + protected DateRangeIndex createRangeIndex(CalendarDay min, CalendarDay max) { + return new BiWeekly(min, max, mcv.getFirstDayOfWeek()); + } + + public static class BiWeekly implements DateRangeIndex { + + private static final int DAYS_IN_TWO_WEEK = 14; + private final CalendarDay min; + private final int count; + /** + * First day of the week to base the weeks on. + */ + private final DayOfWeek firstDayOfWeek; + + public BiWeekly(@NonNull CalendarDay min, @NonNull CalendarDay max, DayOfWeek firstDayOfWeek) { + this.firstDayOfWeek = firstDayOfWeek; + this.min = getFirstDayOfWeek(min); + this.count = indexOf(max) + 1; + } + + @Override + public int getCount() { + return count; + } + + @Override + public int indexOf(CalendarDay day) { + final WeekFields weekFields = WeekFields.of(firstDayOfWeek, 1); + final LocalDate temp = day.getDate().with(weekFields.dayOfWeek(), 1L); + return (int) ChronoUnit.DAYS.between(min.getDate(), temp)/DAYS_IN_TWO_WEEK; + } + + @Override + public CalendarDay getItem(int position) { + return CalendarDay.from(min.getDate().plusDays(Jdk8Methods.safeMultiply(position, DAYS_IN_TWO_WEEK))); + } + + /** + * Getting the first day of a week for a specific date based on a specific week day as first + * day. + */ + private CalendarDay getFirstDayOfWeek(@NonNull final CalendarDay day) { + final LocalDate temp = day.getDate().with(WeekFields.of(firstDayOfWeek, 1).dayOfWeek(), 1L); + return CalendarDay.from(temp); + } + } +} diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/TwoWeekView.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/TwoWeekView.java new file mode 100644 index 00000000..44c77756 --- /dev/null +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/TwoWeekView.java @@ -0,0 +1,41 @@ +package com.prolificinteractive.materialcalendarview; + +import android.annotation.SuppressLint; +import android.support.annotation.NonNull; + +import org.threeten.bp.DayOfWeek; +import org.threeten.bp.LocalDate; + +import java.util.Collection; + +/** + * Display a two week of {@linkplain DayView}s and + * fourteen {@linkplain WeekDayView}s. + */ +@SuppressLint("ViewConstructor") +public class TwoWeekView extends CalendarPagerView { + + public TwoWeekView(@NonNull MaterialCalendarView view, CalendarDay firstViewDay, + final DayOfWeek firstDayOfWeek, boolean showWeekDays) { + super(view, firstViewDay, firstDayOfWeek, showWeekDays); + } + + @Override + protected void buildDayViews(Collection dayViews, final LocalDate calendar) { + LocalDate temp = calendar; + for (int i = 0; i < (DEFAULT_DAYS_IN_WEEK * 2); i++) { + addDayView(dayViews, temp); + temp = temp.plusDays(1); + } + } + + @Override + protected boolean isDayEnabled(CalendarDay day) { + return true; + } + + @Override + protected int getRows() { + return showWeekDays ? DAY_NAMES_ROW + 2 : 2; + } +} diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml index 4946d70a..22cdd15f 100644 --- a/library/src/main/res/values/attrs.xml +++ b/library/src/main/res/values/attrs.xml @@ -53,6 +53,7 @@ + diff --git a/library/src/test/java/com/prolificinteractive/materialcalendarview/BiWeeklyRangeIndexTest.java b/library/src/test/java/com/prolificinteractive/materialcalendarview/BiWeeklyRangeIndexTest.java new file mode 100644 index 00000000..d71b18a5 --- /dev/null +++ b/library/src/test/java/com/prolificinteractive/materialcalendarview/BiWeeklyRangeIndexTest.java @@ -0,0 +1,45 @@ +package com.prolificinteractive.materialcalendarview; + +import org.junit.Test; +import org.threeten.bp.DayOfWeek; +import org.threeten.bp.Month; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +public class BiWeeklyRangeIndexTest { + private static final int _2018 = 2018; + + @Test + public void test2week() { + final CalendarDay startAugust2018 = CalendarDay.from(_2018, Month.AUGUST.getValue(), 14); + final CalendarDay endAugust2018 = CalendarDay.from(_2018, Month.AUGUST.getValue(), 23); + + final DateRangeIndex biWeekly = + new TwoWeekPagerAdapter.BiWeekly(startAugust2018, endAugust2018, DayOfWeek.SUNDAY); + + assertThat(biWeekly.getCount(), equalTo(1)); + + assertThat(biWeekly.getItem(0), equalTo(CalendarDay.from(_2018, Month.AUGUST.getValue(), 12))); + + assertThat(biWeekly.indexOf(startAugust2018), equalTo(0)); + assertThat(biWeekly.indexOf(endAugust2018), equalTo(0)); + } + + @Test + public void test4weeks() { + final CalendarDay startAugust2018 = CalendarDay.from(_2018, Month.AUGUST.getValue(), 2); + final CalendarDay endAugust2018 = CalendarDay.from(_2018, Month.AUGUST.getValue(), 23); + + final DateRangeIndex biWeekly = + new TwoWeekPagerAdapter.BiWeekly(startAugust2018, endAugust2018, DayOfWeek.SUNDAY); + + assertThat(biWeekly.getCount(), equalTo(2)); + + assertThat(biWeekly.getItem(0), equalTo(CalendarDay.from(_2018, Month.JULY.getValue(), 29))); + assertThat(biWeekly.getItem(1), equalTo(CalendarDay.from(_2018, Month.AUGUST.getValue(), 12))); + + assertThat(biWeekly.indexOf(startAugust2018), equalTo(0)); + assertThat(biWeekly.indexOf(endAugust2018), equalTo(1)); + } +} \ No newline at end of file diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/DynamicSettersActivity.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/DynamicSettersActivity.java index 516cdd37..431b84e4 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/DynamicSettersActivity.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/DynamicSettersActivity.java @@ -318,6 +318,14 @@ public void onSetWeekMode() { widget.state().edit().setCalendarDisplayMode(CalendarMode.WEEKS).commit(); } + @OnClick(R.id.button_two_weeks) + public void onSetTwoWeekMode() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && animateModeTransition.isChecked()) { + TransitionManager.beginDelayedTransition(parent); + } + widget.state().edit().setCalendarDisplayMode(CalendarMode.TWO_WEEKS).commit(); + } + @OnClick(R.id.button_months) public void onSetMonthMode() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && animateModeTransition.isChecked()) { diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/SwappableBasicActivityDecorated.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/SwappableBasicActivityDecorated.java index aaa5ba6f..031440d3 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/SwappableBasicActivityDecorated.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/SwappableBasicActivityDecorated.java @@ -66,6 +66,13 @@ public void onSetWeekMode() { .commit(); } + @OnClick(R.id.button_two_weeks) + public void onSetTwoWeekMode() { + widget.state().edit() + .setCalendarDisplayMode(CalendarMode.TWO_WEEKS) + .commit(); + } + @OnClick(R.id.button_months) public void onSetMonthMode() { widget.state().edit() diff --git a/sample/src/main/res/layout/activity_basic_modes.xml b/sample/src/main/res/layout/activity_basic_modes.xml index 43b86338..43a2184f 100644 --- a/sample/src/main/res/layout/activity_basic_modes.xml +++ b/sample/src/main/res/layout/activity_basic_modes.xml @@ -18,27 +18,34 @@ /> - -