From 3aac6652a9a633dd4d75cfbd549c8682c8e70d2e Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 11:00:23 +0200 Subject: [PATCH 01/30] created base views interfaces structures --- .../library/view/BaseView.java | 8 ++++++++ .../library/view/CalendarView.java | 13 +++++++++++++ .../library/view/CustomizableCalendarView.java | 9 +++++++++ .../library/view/HeaderView.java | 8 ++++++++ .../library/view/MonthView.java | 16 ++++++++++++++++ .../library/view/SubView.java | 9 +++++++++ .../library/view/WeekDaysView.java | 9 +++++++++ 7 files changed, 72 insertions(+) create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/BaseView.java create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/CalendarView.java create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/CustomizableCalendarView.java create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/HeaderView.java create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/MonthView.java create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/SubView.java create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/WeekDaysView.java diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/BaseView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/BaseView.java new file mode 100644 index 0000000..81d387c --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/BaseView.java @@ -0,0 +1,8 @@ +package com.francesco.furlan.customizablecalendar.library.view; + +/** + * Created by francescofurlan on 23/06/17. + */ + +public interface BaseView { +} \ No newline at end of file diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/CalendarView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/CalendarView.java new file mode 100644 index 0000000..2e622ab --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/CalendarView.java @@ -0,0 +1,13 @@ +package com.francesco.furlan.customizablecalendar.library.view; + +import android.support.annotation.LayoutRes; + +/** + * Created by francescofurlan on 03/07/17. + */ + +public interface CalendarView extends BaseView { + void setMonthLayoutResId(@LayoutRes int layoutResId); + + void setDayLayoutResId(@LayoutRes int layoutResId); +} diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/CustomizableCalendarView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/CustomizableCalendarView.java new file mode 100644 index 0000000..b3302ce --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/CustomizableCalendarView.java @@ -0,0 +1,9 @@ +package com.francesco.furlan.customizablecalendar.library.view; + +/** + * Created by francescofurlan on 23/06/17. + */ + +public interface CustomizableCalendarView extends BaseView { + void onCurrentMonthChanged(String month); +} diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/HeaderView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/HeaderView.java new file mode 100644 index 0000000..b27c10b --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/HeaderView.java @@ -0,0 +1,8 @@ +package com.francesco.furlan.customizablecalendar.library.view; + +/** + * Created by francescofurlan on 30/06/17. + */ + +public interface HeaderView extends BaseView { +} diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/MonthView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/MonthView.java new file mode 100644 index 0000000..bab490b --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/MonthView.java @@ -0,0 +1,16 @@ +package com.francesco.furlan.customizablecalendar.library.view; + + +import org.joda.time.DateTime; + +/** + * Created by francescofurlan on 23/06/17. + */ + +public interface MonthView extends BaseView { + void setSelected(DateTime dateSelected); + + void refreshDays(); + + void unsubscribe(); +} diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/SubView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/SubView.java new file mode 100644 index 0000000..2e9d26b --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/SubView.java @@ -0,0 +1,9 @@ +package com.francesco.furlan.customizablecalendar.library.view; + +/** + * Created by francescofurlan on 30/06/17. + */ + +public interface SubView extends BaseView { + void onMonthChanged(String month); +} diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/WeekDaysView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/WeekDaysView.java new file mode 100644 index 0000000..470d84e --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/WeekDaysView.java @@ -0,0 +1,9 @@ +package com.francesco.furlan.customizablecalendar.library.view; + +/** + * Created by francescofurlan on 30/06/17. + */ + +public interface WeekDaysView extends BaseView { + void onFirstDayOfWeek(int firstDayOfWeek); +} From b254214c94a0846670e3e6869b86f42e2f0f2ea4 Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 11:02:35 +0200 Subject: [PATCH 02/30] created BasePresenter --- .../presenter/interfeaces/BasePresenter.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/interfeaces/BasePresenter.java diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/interfeaces/BasePresenter.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/interfeaces/BasePresenter.java new file mode 100644 index 0000000..7388fc6 --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/interfeaces/BasePresenter.java @@ -0,0 +1,19 @@ +package com.francesco.furlan.customizablecalendar.library.presenter.interfeaces; + +import android.support.annotation.LayoutRes; +import android.view.View; + +import com.francesco.furlan.customizablecalendar.library.interactors.ViewInteractor; +import com.francesco.furlan.customizablecalendar.library.view.BaseView; + +/** + * Created by francescofurlan on 23/06/17. + */ + +public interface BasePresenter { + void setView(T view); + + void onBindView(View rootView); + + void setLayoutResId(@LayoutRes int layoutResId); +} \ No newline at end of file From 3c255b8404d243a26c0760fd7176944ff30932ac Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 11:07:27 +0200 Subject: [PATCH 03/30] implemented weekDay, subView and calendar layouts --- .../src/main/res/drawable/empty_circle.xml | 19 +++++++++ library/src/main/res/layout/calendar_cell.xml | 40 +++++++++++++++++++ library/src/main/res/layout/calendar_view.xml | 16 ++++++++ library/src/main/res/layout/sub_view.xml | 14 +++++++ library/src/main/res/layout/week_day_view.xml | 15 +++++++ 5 files changed, 104 insertions(+) create mode 100644 library/src/main/res/drawable/empty_circle.xml create mode 100644 library/src/main/res/layout/calendar_cell.xml create mode 100644 library/src/main/res/layout/calendar_view.xml create mode 100644 library/src/main/res/layout/sub_view.xml create mode 100644 library/src/main/res/layout/week_day_view.xml diff --git a/library/src/main/res/drawable/empty_circle.xml b/library/src/main/res/drawable/empty_circle.xml new file mode 100644 index 0000000..4ecefb9 --- /dev/null +++ b/library/src/main/res/drawable/empty_circle.xml @@ -0,0 +1,19 @@ + + + + + + + + \ No newline at end of file diff --git a/library/src/main/res/layout/calendar_cell.xml b/library/src/main/res/layout/calendar_cell.xml new file mode 100644 index 0000000..75e6084 --- /dev/null +++ b/library/src/main/res/layout/calendar_cell.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/library/src/main/res/layout/calendar_view.xml b/library/src/main/res/layout/calendar_view.xml new file mode 100644 index 0000000..a8f4f0e --- /dev/null +++ b/library/src/main/res/layout/calendar_view.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/library/src/main/res/layout/sub_view.xml b/library/src/main/res/layout/sub_view.xml new file mode 100644 index 0000000..667c026 --- /dev/null +++ b/library/src/main/res/layout/sub_view.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/library/src/main/res/layout/week_day_view.xml b/library/src/main/res/layout/week_day_view.xml new file mode 100644 index 0000000..dfb1096 --- /dev/null +++ b/library/src/main/res/layout/week_day_view.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file From a6019f6ab5ac9e67d49a6cde6c8c3c82777ce8e7 Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 11:08:07 +0200 Subject: [PATCH 04/30] implemented CustomizableCalendar stylable --- library/src/main/res/values/attrs.xml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 library/src/main/res/values/attrs.xml diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml new file mode 100644 index 0000000..08d708c --- /dev/null +++ b/library/src/main/res/values/attrs.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file From a97423b0cb399f2c51bcc2ed237e92240fb4d544 Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 11:09:37 +0200 Subject: [PATCH 05/30] implemented Calendar and CalendarItem models and CalendarFields interface --- .../library/model/Calendar.java | 92 +++++++++++++++++++ .../library/model/CalendarFields.java | 36 ++++++++ .../library/model/CalendarItem.java | 74 +++++++++++++++ 3 files changed, 202 insertions(+) create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/model/Calendar.java create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/model/CalendarFields.java create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/model/CalendarItem.java diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/model/Calendar.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/model/Calendar.java new file mode 100644 index 0000000..aa6c480 --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/model/Calendar.java @@ -0,0 +1,92 @@ +package com.francesco.furlan.customizablecalendar.library.model; + +import org.joda.time.DateTime; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +/** + * Created by francescofurlan on 27/06/17. + */ + +public class Calendar { + private DateTime firstMonth; + private DateTime firstSelectedDay; + private DateTime lastSelectedDay; + private DateTime currentMonth; + private List months; + private boolean multipleSelection; + private int firstDayOfWeek; + + public Calendar(DateTime firstMonth, DateTime lastMonth) { + this.firstMonth = firstMonth; + this.firstDayOfWeek = java.util.Calendar.getInstance(Locale.getDefault()).getFirstDayOfWeek(); + + int startMonth = firstMonth.getMonthOfYear()+1; + int endMonth = lastMonth.getMonthOfYear(); + + months = new ArrayList<>(); + + months.add(firstMonth); + currentMonth = firstMonth; + + DateTime monthToAdd = new DateTime(firstMonth.getYear(), startMonth, 1, 0, 0); + for (int i = startMonth; i <= endMonth; i++) { + months.add(monthToAdd); + monthToAdd = monthToAdd.plusMonths(1); + } + } + + public DateTime getFirstSelectedDay() { + return firstSelectedDay; + } + + public void setFirstSelectedDay(DateTime firstSelectedDay) { + this.firstSelectedDay = firstSelectedDay; + } + + public DateTime getLastSelectedDay() { + return lastSelectedDay; + } + + public void setLastSelectedDay(DateTime lastSelectedDay) { + this.lastSelectedDay = lastSelectedDay; + } + + public DateTime getCurrentMonth() { + return currentMonth; + } + + public void setCurrentMonth(DateTime currentMonth) { + this.currentMonth = currentMonth; + } + + public List getMonths() { + return months; + } + + public void setMonths(List months) { + this.months = months; + } + + public boolean isMultipleSelectionEnabled() { + return multipleSelection; + } + + public void setMultipleSelection(boolean multipleSelection) { + this.multipleSelection = multipleSelection; + } + + public int getFirstDayOfWeek() { + return firstDayOfWeek; + } + + public void setFirstDayOfWeek(int firstDayOfWeek) { + this.firstDayOfWeek = firstDayOfWeek; + } + + public DateTime getFirstMonth() { + return firstMonth; + } +} diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/model/CalendarFields.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/model/CalendarFields.java new file mode 100644 index 0000000..b393cb7 --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/model/CalendarFields.java @@ -0,0 +1,36 @@ +package com.francesco.furlan.customizablecalendar.library.model; + +import android.support.annotation.StringDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import static com.francesco.furlan.customizablecalendar.library.model.CalendarFields.CURRENT_MONTH; +import static com.francesco.furlan.customizablecalendar.library.model.CalendarFields.FIRST_DAY_OF_WEEK; +import static com.francesco.furlan.customizablecalendar.library.model.CalendarFields.FIRST_SELECTED_DAY; +import static com.francesco.furlan.customizablecalendar.library.model.CalendarFields.LAST_SELECTED_DAY; +import static com.francesco.furlan.customizablecalendar.library.model.CalendarFields.MONTHS; +import static com.francesco.furlan.customizablecalendar.library.model.CalendarFields.MULTIPLE_SELECTION; + +/** + * Created by francescofurlan on 30/06/17. + */ + +@StringDef({ + FIRST_SELECTED_DAY, + LAST_SELECTED_DAY, + CURRENT_MONTH, + MONTHS, + MULTIPLE_SELECTION, + FIRST_DAY_OF_WEEK +}) + +@Retention(RetentionPolicy.SOURCE) +public @interface CalendarFields { + String FIRST_SELECTED_DAY = "firstSelectedDay"; + String LAST_SELECTED_DAY = "lastSelectedDay"; + String CURRENT_MONTH = "currentMonth"; + String MONTHS = "months"; + String MULTIPLE_SELECTION = "multipleSelection"; + String FIRST_DAY_OF_WEEK = "firstDayOfWeek"; +} \ No newline at end of file diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/model/CalendarItem.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/model/CalendarItem.java new file mode 100644 index 0000000..be592f5 --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/model/CalendarItem.java @@ -0,0 +1,74 @@ +package com.francesco.furlan.customizablecalendar.library.model; + +import org.joda.time.DateTime; + +import java.util.Calendar; + +/** + * Created by francescofurlan on 23/06/17. + */ + +public class CalendarItem { + private long id; + private DateTime dateTime; + private boolean selected; + + public CalendarItem(Calendar calendar) { + this.dateTime = new DateTime(calendar); + this.id = calendar.getTimeInMillis(); + } + + public CalendarItem(DateTime dateTime) { + this.dateTime = dateTime; + this.id = dateTime.getMillis(); + } + + public CalendarItem(int day, int month, int year) { + this.dateTime = new DateTime(year, month, day, 0, 0); + this.id = dateTime.getMillis(); + } + + public DateTime getDateTime() { + return dateTime; + } + + public void setDateTime(DateTime dateTime) { + this.dateTime = dateTime; + } + + public boolean isSelectable() { + return selected; + } + + public void setSelectable(boolean selected) { + this.selected = selected; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public int compareTo(DateTime today) { + return dateTime.compareTo(today); + } + + public String getDayString() { + return getDay() + ""; + } + + public int getDay() { + return dateTime.getDayOfMonth(); + } + + public int getMonth() { + return dateTime.getMonthOfYear(); + } + + public int getYear() { + return dateTime.getYear(); + } +} From 3a7fbd4fd3fc9917731c69ed543bffb6f826ea0c Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 11:38:23 +0200 Subject: [PATCH 06/30] added basics views implementations --- .../components/CalendarRecyclerView.java | 30 +++++++++++ .../components/CustomizableCalendar.java | 50 +++++++++++++++++++ .../library/components/HeaderView.java | 30 +++++++++++ .../library/components/MonthGridView.java | 35 +++++++++++++ .../library/components/SubView.java | 27 ++++++++++ .../library/components/WeekDaysView.java | 38 ++++++++++++++ 6 files changed, 210 insertions(+) create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CalendarRecyclerView.java create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CustomizableCalendar.java create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/HeaderView.java create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/MonthGridView.java create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/SubView.java create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/WeekDaysView.java diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CalendarRecyclerView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CalendarRecyclerView.java new file mode 100644 index 0000000..171b299 --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CalendarRecyclerView.java @@ -0,0 +1,30 @@ +package com.francesco.furlan.customizablecalendar.library.components; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; + +/** + * Created by francescofurlan on 23/06/17. + */ + +public class CalendarRecyclerView extends RecyclerView { + private Context context; + + public CalendarRecyclerView(Context context) { + this(context, null); + } + + public CalendarRecyclerView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public CalendarRecyclerView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(context); + } + + private void init(Context context) { + this.context = context; + } +} \ No newline at end of file diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CustomizableCalendar.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CustomizableCalendar.java new file mode 100644 index 0000000..59019db --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CustomizableCalendar.java @@ -0,0 +1,50 @@ +package com.francesco.furlan.customizablecalendar.library.components; + +import android.content.Context; +import android.content.res.TypedArray; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.widget.LinearLayout; + +import com.francesco.furlan.customizablecalendar.library.R; + +import butterknife.InjectView; + +/** + * Created by francescofurlan on 23/06/17. + */ + +public class CustomizableCalendar extends LinearLayout { + + @InjectView(android.R.id.primary) + HeaderView headerView; + + @InjectView(android.R.id.text1) + WeekDaysView weekDaysView; + + @InjectView(android.R.id.text2) + SubView subView; + + @InjectView(android.R.id.content) + CalendarRecyclerView calendarRecyclerView; + + public CustomizableCalendar(Context context) { + this(context, null); + } + + public CustomizableCalendar(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public CustomizableCalendar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs, defStyleAttr); + } + + private void init(Context context, AttributeSet attrs, int defStyleAttr) { + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomizableCalendar); + if (typedArray != null) { + typedArray.recycle(); + } + } +} \ No newline at end of file diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/HeaderView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/HeaderView.java new file mode 100644 index 0000000..a3e519d --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/HeaderView.java @@ -0,0 +1,30 @@ +package com.francesco.furlan.customizablecalendar.library.components; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.RelativeLayout; + +/** + * Created by francescofurlan on 23/06/17. + */ + +public class HeaderView extends RelativeLayout { + private Context context; + + public HeaderView(Context context) { + this(context, null); + } + + public HeaderView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public HeaderView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context); + } + + private void init(Context context) { + this.context = context; + } +} \ No newline at end of file diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/MonthGridView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/MonthGridView.java new file mode 100644 index 0000000..bfdb1b0 --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/MonthGridView.java @@ -0,0 +1,35 @@ +package com.francesco.furlan.customizablecalendar.library.components; + +import android.content.Context; +import android.content.res.TypedArray; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.widget.LinearLayout; + +import com.francesco.furlan.customizablecalendar.library.R; + +/** + * Created by francescofurlan on 23/06/17. + */ + +public class MonthGridView extends LinearLayout { + public MonthGridView(Context context) { + this(context, null); + } + + public MonthGridView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public MonthGridView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs); + } + + private void init(Context context, AttributeSet attrs) { + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomizableCalendar); + if (typedArray != null) { + typedArray.recycle(); + } + } +} diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/SubView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/SubView.java new file mode 100644 index 0000000..df16e91 --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/SubView.java @@ -0,0 +1,27 @@ +package com.francesco.furlan.customizablecalendar.library.components; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.RelativeLayout; + +/** + * Created by francescofurlan on 23/06/17. + */ + +public class SubView extends RelativeLayout { + public SubView(Context context) { + this(context, null); + } + + public SubView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SubView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs); + } + + private void init(Context context, AttributeSet attrs) { + } +} diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/WeekDaysView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/WeekDaysView.java new file mode 100644 index 0000000..fb613b3 --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/WeekDaysView.java @@ -0,0 +1,38 @@ +package com.francesco.furlan.customizablecalendar.library.components; + +import android.content.Context; +import android.content.res.TypedArray; +import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; + +import com.francesco.furlan.customizablecalendar.library.R; + +/** + * Created by francescofurlan on 23/06/17. + */ + +public class WeekDaysView extends RecyclerView { + private Context context; + + public WeekDaysView(Context context) { + this(context, null); + } + + public WeekDaysView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public WeekDaysView(Context context, @Nullable AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(context, attrs); + } + + private void init(Context context, AttributeSet attrs) { + this.context = context; + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomizableCalendar); + if (typedArray != null) { + typedArray.recycle(); + } + } +} From 1cc589220f7521afc6aab201484bb519f9f224a1 Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 11:40:53 +0200 Subject: [PATCH 07/30] updated gradle dependencies --- library/build.gradle | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/library/build.gradle b/library/build.gradle index df0502b..59c9909 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -1,4 +1,5 @@ apply plugin: 'com.android.library' +apply plugin: 'me.tatarka.retrolambda' android { compileSdkVersion 25 @@ -19,6 +20,10 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } } dependencies { @@ -27,5 +32,14 @@ dependencies { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.3.1' + compile 'com.android.support:recyclerview-v7:25.3.1' testCompile 'junit:junit:4.12' + compile 'joda-time:joda-time:2.9.9' + compile 'com.jakewharton:butterknife:6.1.0' + compile "io.reactivex.rxjava2:rxjava:2.0.1" + retrolambdaConfig 'net.orfjackal.retrolambda:retrolambda:2.5.1' +} + +retrolambda { + javaVersion JavaVersion.VERSION_1_7 } \ No newline at end of file From 781e9a5a0004dbe676f57ab787a69b47112542be Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 11:42:46 +0200 Subject: [PATCH 08/30] implemented AUCalendar -> Auto Updating Calendar --- .../library/interactors/AUCalendar.java | 175 ++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/AUCalendar.java diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/AUCalendar.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/AUCalendar.java new file mode 100644 index 0000000..f39d5cd --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/AUCalendar.java @@ -0,0 +1,175 @@ +package com.francesco.furlan.customizablecalendar.library.interactors; + +import com.francesco.furlan.customizablecalendar.library.model.Calendar; +import com.francesco.furlan.customizablecalendar.library.model.CalendarFields; + +import org.joda.time.DateTime; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.BackpressureStrategy; +import io.reactivex.Flowable; +import io.reactivex.FlowableEmitter; + +/** + * Created by francescofurlan on 30/06/17. + */ + +public class AUCalendar { + private Calendar calendar; + private static AUCalendar AUCalendarInstance; + + public static AUCalendar getInstance() { + if (AUCalendarInstance == null) { + AUCalendarInstance = new AUCalendar(); + } + return AUCalendarInstance; + } + + public static AUCalendar getInstance(Calendar calendar) { + getInstance(); + if (calendar != null) { + AUCalendarInstance.setCalendar(calendar); + } + return AUCalendarInstance; + } + + public DateTime getFirstMonth() { + return calendar.getFirstMonth(); + } + + public interface ChangeSet { + List getChangedFields(); + + boolean isFieldChanged(String fieldName); + + String toString(); + } + + private class CalendarChangeSet implements ChangeSet { + private List changedFields = new ArrayList<>(); + + public void setChangedFiels(List changedFields) { + this.changedFields = changedFields; + } + + public void addChangedField(String changedField) { + this.changedFields.add(changedField); + } + + @Override + public List getChangedFields() { + return changedFields; + } + + @Override + public boolean isFieldChanged(String fieldName) { + return changedFields.contains(fieldName); + } + @Override + public String toString() { + String fieldChanges = ""; + for (String fieldChanged : changedFields) { + fieldChanges += " " + fieldChanged; + } + return fieldChanges; + } + } + + public interface CalendarObjectChangeListener { + void onChange(ChangeSet changeSet); + } + + private List onChangeListenerList = new ArrayList<>(); + + public void setCalendar(Calendar calendar) { + this.calendar = calendar; + } + + public Calendar getCalendar() { + return calendar; + } + + public Flowable observeChangesOnCalendar() { + return Flowable.create((FlowableEmitter emitter) -> { + CalendarObjectChangeListener objectChangeListener = emitter::onNext; + addChangeListener(objectChangeListener); + emitter.setCancellable(() -> removeChangeListener(objectChangeListener)); + }, BackpressureStrategy.BUFFER); + } + + private void addChangeListener(CalendarObjectChangeListener objectChangeListener) { + onChangeListenerList.add(objectChangeListener); + } + + private void removeChangeListener(CalendarObjectChangeListener objectChangeListener) { + onChangeListenerList.remove(objectChangeListener); + } + + private void emitOnChange(ChangeSet changeSet) { + for (CalendarObjectChangeListener onChangeListener : onChangeListenerList) { + onChangeListener.onChange(changeSet); + } + } + + private void emitOnChange(String changedField) { + CalendarChangeSet changeSet = new CalendarChangeSet(); + changeSet.addChangedField(changedField); + emitOnChange(changeSet); + } + + public DateTime getFirstSelectedDay() { + return calendar.getFirstSelectedDay(); + } + + public void setFirstSelectedDay(DateTime firstSelectedDay) { + calendar.setFirstSelectedDay(firstSelectedDay); + emitOnChange(CalendarFields.FIRST_SELECTED_DAY); + } + + public DateTime getLastSelectedDay() { + return calendar.getLastSelectedDay(); + } + + public void setLastSelectedDay(DateTime lastSelectedDay) { + calendar.setLastSelectedDay(lastSelectedDay); + emitOnChange(CalendarFields.LAST_SELECTED_DAY); + } + + public DateTime getCurrentMonth() { + return calendar.getCurrentMonth(); + } + + public void setCurrentMonth(DateTime currentMonth) { + calendar.setCurrentMonth(currentMonth); + emitOnChange(CalendarFields.CURRENT_MONTH); + } + + public List getMonths() { + return calendar.getMonths(); + } + + public void setMonths(List months) { + calendar.setMonths(months); + emitOnChange(CalendarFields.MONTHS); + } + + public boolean isMultipleSelectionEnabled() { + return calendar.isMultipleSelectionEnabled(); + } + + public void setMultipleSelection(boolean multipleSelection) { + calendar.setMultipleSelection(multipleSelection); + emitOnChange(CalendarFields.MULTIPLE_SELECTION); + } + + public int getFirstDayOfWeek() { + return calendar.getFirstDayOfWeek(); + } + + public void setFirstDayOfWeek(int firstDayOfWeek) { + calendar.setFirstDayOfWeek(firstDayOfWeek); + emitOnChange(CalendarFields.FIRST_DAY_OF_WEEK); + } +} \ No newline at end of file From 6ff181ed1d29613471e4bd20c8d373344eed706f Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 11:43:03 +0200 Subject: [PATCH 09/30] added DateUtils --- .../library/utils/DateUtils.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/utils/DateUtils.java diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/utils/DateUtils.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/utils/DateUtils.java new file mode 100644 index 0000000..b1998ea --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/utils/DateUtils.java @@ -0,0 +1,31 @@ +package com.francesco.furlan.customizablecalendar.library.utils; + +import java.util.Calendar; + +/** + * Created by francescofurlan on 23/06/17. + */ + +public class DateUtils { + public static int getDaysInMonth(int month, int year) { + switch (month) { + case Calendar.JANUARY: + case Calendar.MARCH: + case Calendar.MAY: + case Calendar.JULY: + case Calendar.AUGUST: + case Calendar.OCTOBER: + case Calendar.DECEMBER: + return 31; + case Calendar.APRIL: + case Calendar.JUNE: + case Calendar.SEPTEMBER: + case Calendar.NOVEMBER: + return 30; + case Calendar.FEBRUARY: + return (year % 4 == 0) ? 29 : 28; + default: + throw new IllegalArgumentException("Invalid Month"); + } + } +} \ No newline at end of file From d9c6b9650e301cda45c52c4cb4179a2e6b9b878a Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 11:44:20 +0200 Subject: [PATCH 10/30] created LayoutInteractor, ViewInjector and ViewInteractor interfaces --- .../library/interactors/LayoutInteractor.java | 21 +++++++++ .../library/interactors/ViewInjector.java | 20 +++++++++ .../library/interactors/ViewInteractor.java | 43 +++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/LayoutInteractor.java create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/ViewInjector.java create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/ViewInteractor.java diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/LayoutInteractor.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/LayoutInteractor.java new file mode 100644 index 0000000..835e67e --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/LayoutInteractor.java @@ -0,0 +1,21 @@ +package com.francesco.furlan.customizablecalendar.library.interactors; + +import android.support.annotation.LayoutRes; + +/** + * Created by francescofurlan on 26/06/17. + */ + +public interface LayoutInteractor { + void setCustomizableCalendarLayoutResId(@LayoutRes int resId); + + void setHeaderLayoutResId(@LayoutRes int resId); + + void setWeekDayResId(@LayoutRes int resId); + + void setSubViewResId(@LayoutRes int resId); + + void setMonthResId(@LayoutRes int resId); + + void setDayResId(@LayoutRes int resId); +} diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/ViewInjector.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/ViewInjector.java new file mode 100644 index 0000000..84e8097 --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/ViewInjector.java @@ -0,0 +1,20 @@ +package com.francesco.furlan.customizablecalendar.library.interactors; + +import com.francesco.furlan.customizablecalendar.library.view.CalendarView; +import com.francesco.furlan.customizablecalendar.library.view.HeaderView; +import com.francesco.furlan.customizablecalendar.library.view.SubView; +import com.francesco.furlan.customizablecalendar.library.view.WeekDaysView; + +/** + * Created by francescofurlan on 30/06/17. + */ + +public interface ViewInjector { + void injectCalendarView(CalendarView calendarView); + + void injectHeaderView(HeaderView headerView); + + void injectSubView(SubView subView); + + void injectWeekDaysView(WeekDaysView weekDaysView); +} diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/ViewInteractor.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/ViewInteractor.java new file mode 100644 index 0000000..df0c460 --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/ViewInteractor.java @@ -0,0 +1,43 @@ +package com.francesco.furlan.customizablecalendar.library.interactors; + +import android.view.View; +import android.view.ViewGroup; + +import com.francesco.furlan.customizablecalendar.library.adapter.WeekDaysViewAdapter; +import com.francesco.furlan.customizablecalendar.library.model.CalendarItem; + +import org.joda.time.DateTime; + +import java.util.List; + +/** + * Created by francescofurlan on 26/06/17. + */ + +public interface ViewInteractor { + void onCustomizableCalendarBindView(View view); + + void onHeaderBindView(ViewGroup view); + + void onWeekDaysBindView(View view); + + void onWeekDayBindView(WeekDaysViewAdapter.WeekDayVH holder, String weekDay); + + void onSubViewBindView(View view, String month); + + void onCalendarBindView(View view); + + void onMonthBindView(View view); + + void onMonthCellBindView(View view); + + boolean hasImplementedDayCalculation(); + + List calculateDays(int year, int month, int firstDayOfMonth, int lastDayOfMonth); + + boolean hasImplementedSelection(); + + int setSelected(boolean multipleSelection, DateTime dateSelected); + + boolean hasImplementedMonthCellBinding(); +} From 068ebbdc2484755dfa24272b6986fec3b36dc6b1 Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 11:47:04 +0200 Subject: [PATCH 11/30] updated BaseView and BasePresenter with new injectors and created CustomizableCalendarPresenter --- .../library/presenter/interfeaces/BasePresenter.java | 2 ++ .../interfeaces/CustomizableCalendarPresenter.java | 12 ++++++++++++ .../customizablecalendar/library/view/BaseView.java | 12 ++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/interfeaces/CustomizableCalendarPresenter.java diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/interfeaces/BasePresenter.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/interfeaces/BasePresenter.java index 7388fc6..b116444 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/interfeaces/BasePresenter.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/interfeaces/BasePresenter.java @@ -15,5 +15,7 @@ public interface BasePresenter { void onBindView(View rootView); + void injectViewInteractor(ViewInteractor viewInteractor); + void setLayoutResId(@LayoutRes int layoutResId); } \ No newline at end of file diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/interfeaces/CustomizableCalendarPresenter.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/interfeaces/CustomizableCalendarPresenter.java new file mode 100644 index 0000000..e2bf6ce --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/interfeaces/CustomizableCalendarPresenter.java @@ -0,0 +1,12 @@ +package com.francesco.furlan.customizablecalendar.library.presenter.interfeaces; + +import com.francesco.furlan.customizablecalendar.library.interactors.LayoutInteractor; +import com.francesco.furlan.customizablecalendar.library.interactors.ViewInjector; +import com.francesco.furlan.customizablecalendar.library.view.CustomizableCalendarView; + +/** + * Created by francescofurlan on 23/06/17. + */ + +public interface CustomizableCalendarPresenter extends BasePresenter, ViewInjector, LayoutInteractor { +} diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/BaseView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/BaseView.java index 81d387c..059a98b 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/BaseView.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/view/BaseView.java @@ -1,8 +1,20 @@ package com.francesco.furlan.customizablecalendar.library.view; +import android.support.annotation.LayoutRes; + +import com.francesco.furlan.customizablecalendar.library.interactors.ViewInteractor; +import com.francesco.furlan.customizablecalendar.library.presenter.interfeaces.CustomizableCalendarPresenter; + /** * Created by francescofurlan on 23/06/17. */ public interface BaseView { + void refreshData(); + + void setLayoutResId(@LayoutRes int layoutResId); + + void injectViewInteractor(ViewInteractor viewInteractor); + + void injectPresenter(CustomizableCalendarPresenter presenter); } \ No newline at end of file From dadac9e0d22dd0f5b4cb058fd88f0db92c49d212 Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 11:49:05 +0200 Subject: [PATCH 12/30] implemented WeekDaysView --- .../library/adapter/WeekDaysViewAdapter.java | 87 ++++++++++++++++++ .../library/components/WeekDaysView.java | 89 ++++++++++++++++++- 2 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/WeekDaysViewAdapter.java diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/WeekDaysViewAdapter.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/WeekDaysViewAdapter.java new file mode 100644 index 0000000..59e50fe --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/WeekDaysViewAdapter.java @@ -0,0 +1,87 @@ +package com.francesco.furlan.customizablecalendar.library.adapter; + +import android.content.Context; +import android.support.annotation.LayoutRes; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.francesco.furlan.customizablecalendar.library.R; +import com.francesco.furlan.customizablecalendar.library.interactors.ViewInteractor; + +import java.util.ArrayList; +import java.util.List; + +import butterknife.ButterKnife; +import butterknife.InjectView; + +/** + * Created by francescofurlan on 28/06/17. + */ + +public class WeekDaysViewAdapter extends RecyclerView.Adapter { + + private Context context; + private List weekDays = new ArrayList<>(); + private ItemClickListener clickListener; + private ViewInteractor viewInteractor; + private @LayoutRes int layoutResId; + + public WeekDaysViewAdapter(Context context, List weekDays, @LayoutRes int layoutResId, ViewInteractor viewInteractor) { + this.context = context; + this.weekDays = weekDays; + this.layoutResId = layoutResId; + this.viewInteractor = viewInteractor; + } + + @Override + public WeekDayVH onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(context).inflate(layoutResId, parent, false); + return new WeekDayVH(view); + } + + @Override + public void onBindViewHolder(WeekDayVH holder, int position) { + String weekDay = getItem(position); + holder.weekDayTxt.setText(weekDay); + viewInteractor.onWeekDayBindView(holder, weekDay); + } + + @Override + public int getItemCount() { + return weekDays.size(); + } + + + public class WeekDayVH extends RecyclerView.ViewHolder implements View.OnClickListener { + TextView weekDayTxt; + + public WeekDayVH(View itemView) { + super(itemView); + weekDayTxt = (TextView) itemView.findViewById(android.R.id.summary); + itemView.setOnClickListener(this); + } + + @Override + public void onClick(View view) { + if (clickListener != null) { + clickListener.onItemClick(view, getAdapterPosition()); + } + } + } + + public String getItem(int position) { + return weekDays.get(position); + } + + public void setClickListener(ItemClickListener clickListener) { + this.clickListener = clickListener; + } + + public interface ItemClickListener { + void onItemClick(View view, int position); + } +} + diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/WeekDaysView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/WeekDaysView.java index fb613b3..8cf83dc 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/WeekDaysView.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/WeekDaysView.java @@ -2,18 +2,37 @@ import android.content.Context; import android.content.res.TypedArray; +import android.support.annotation.LayoutRes; import android.support.annotation.Nullable; +import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; import android.util.AttributeSet; import com.francesco.furlan.customizablecalendar.library.R; +import com.francesco.furlan.customizablecalendar.library.adapter.WeekDaysViewAdapter; +import com.francesco.furlan.customizablecalendar.library.interactors.AUCalendar; +import com.francesco.furlan.customizablecalendar.library.interactors.ViewInteractor; +import com.francesco.furlan.customizablecalendar.library.presenter.interfeaces.CustomizableCalendarPresenter; + +import java.text.DateFormatSymbols; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.Locale; /** * Created by francescofurlan on 23/06/17. */ -public class WeekDaysView extends RecyclerView { +public class WeekDaysView extends RecyclerView implements com.francesco.furlan.customizablecalendar.library.view.WeekDaysView { + WeekDaysViewAdapter weekDaysViewAdapter; private Context context; + private @LayoutRes int layoutResId = -1; + private @LayoutRes int dayLayoutResId = -1; + private ViewInteractor viewInteractor; + private Integer firstDayOfWeek; + private CustomizableCalendarPresenter presenter; public WeekDaysView(Context context) { this(context, null); @@ -31,8 +50,76 @@ public WeekDaysView(Context context, @Nullable AttributeSet attrs, int defStyle) private void init(Context context, AttributeSet attrs) { this.context = context; TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomizableCalendar); + layoutResId = R.layout.week_day_view; if (typedArray != null) { + layoutResId = typedArray.getResourceId(R.styleable.CustomizableCalendar_weekDayLayout, R.layout.week_day_view); typedArray.recycle(); } } + + private String getFormattedDayOfDay(String nameOfDay) { + if (!TextUtils.isEmpty(nameOfDay)) { + return nameOfDay.substring(0, 1).toUpperCase(); + } + return null; + } + + public void setWeekDays(List weekDays) { + weekDaysViewAdapter = new WeekDaysViewAdapter(context, weekDays, layoutResId, viewInteractor); + setAdapter(weekDaysViewAdapter); + setLayoutManager(new GridLayoutManager(context, weekDays.size())); + } + + @Override + public void refreshData() { + + } + + @Override + public void setLayoutResId(@LayoutRes int layoutResId) { + this.layoutResId = layoutResId; + } + + @Override + public void injectViewInteractor(ViewInteractor viewInteractor) { + this.viewInteractor = viewInteractor; + setupWeekDays(); + } + + @Override + public void injectPresenter(CustomizableCalendarPresenter presenter) { + this.presenter = presenter; + presenter.injectWeekDaysView(this); + } + + @Override + public void onFirstDayOfWeek(int firstDayOfWeek) { + this.firstDayOfWeek = firstDayOfWeek; + setupWeekDays(); + } + + private void setupWeekDays() { + viewInteractor.onWeekDaysBindView(this); + String[] namesOfDays = DateFormatSymbols.getInstance(Locale.getDefault()).getShortWeekdays(); + if (firstDayOfWeek == null) { + firstDayOfWeek = AUCalendar.getInstance().getFirstDayOfWeek(); + } + + List weekDays = new ArrayList<>(); + for (int i = firstDayOfWeek; i < namesOfDays.length; i++) { + String nameOfDay = namesOfDays[i]; + String formattedNameOfDay = getFormattedDayOfDay(nameOfDay); + if (formattedNameOfDay != null) { + weekDays.add(formattedNameOfDay); + } + } + for (int i = 0; i < firstDayOfWeek; i++) { + String nameOfDay = namesOfDays[i]; + String formattedNameOfDay = getFormattedDayOfDay(nameOfDay); + if (formattedNameOfDay != null) { + weekDays.add(formattedNameOfDay); + } + } + setWeekDays(weekDays); + } } From 2c35ed8bb2a49eda0d3d1065bcc3fab5ec36f88b Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 11:49:26 +0200 Subject: [PATCH 13/30] implemented HeaderView --- .../library/components/HeaderView.java | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/HeaderView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/HeaderView.java index a3e519d..a1dc3eb 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/HeaderView.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/HeaderView.java @@ -1,14 +1,21 @@ package com.francesco.furlan.customizablecalendar.library.components; import android.content.Context; +import android.support.annotation.LayoutRes; import android.util.AttributeSet; +import android.view.LayoutInflater; import android.widget.RelativeLayout; +import com.francesco.furlan.customizablecalendar.library.interactors.ViewInteractor; +import com.francesco.furlan.customizablecalendar.library.presenter.interfeaces.CustomizableCalendarPresenter; + /** * Created by francescofurlan on 23/06/17. */ -public class HeaderView extends RelativeLayout { +public class HeaderView extends RelativeLayout implements com.francesco.furlan.customizablecalendar.library.view.HeaderView { + private CustomizableCalendarPresenter presenter; + private ViewInteractor viewInteractor; private Context context; public HeaderView(Context context) { @@ -27,4 +34,28 @@ public HeaderView(Context context, AttributeSet attrs, int defStyleAttr) { private void init(Context context) { this.context = context; } + + @Override + public void refreshData() { + + } + + @Override + public void setLayoutResId(@LayoutRes int layoutResId) { + if (layoutResId != -1) { + LayoutInflater.from(context).inflate(layoutResId, this); + } + } + + @Override + public void injectViewInteractor(ViewInteractor viewInteractor) { + this.viewInteractor = viewInteractor; + this.viewInteractor.onHeaderBindView(this); + } + + @Override + public void injectPresenter(CustomizableCalendarPresenter presenter) { + this.presenter = presenter; + this.presenter.injectHeaderView(this); + } } \ No newline at end of file From 74203969d03c0d439a5c14f7c752191adaaae689 Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 11:49:42 +0200 Subject: [PATCH 14/30] implemented SubView --- .../library/components/SubView.java | 64 ++++++++++++++++++- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/SubView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/SubView.java index df16e91..6c3735c 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/SubView.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/SubView.java @@ -1,14 +1,38 @@ package com.francesco.furlan.customizablecalendar.library.components; import android.content.Context; +import android.support.annotation.LayoutRes; +import android.text.TextUtils; import android.util.AttributeSet; +import android.view.LayoutInflater; import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.francesco.furlan.customizablecalendar.library.R; +import com.francesco.furlan.customizablecalendar.library.interactors.AUCalendar; +import com.francesco.furlan.customizablecalendar.library.interactors.ViewInteractor; +import com.francesco.furlan.customizablecalendar.library.presenter.interfeaces.CustomizableCalendarPresenter; + +import org.joda.time.DateTime; + +import java.util.Locale; + +import butterknife.ButterKnife; +import butterknife.InjectView; /** * Created by francescofurlan on 23/06/17. */ -public class SubView extends RelativeLayout { +public class SubView extends RelativeLayout implements com.francesco.furlan.customizablecalendar.library.view.SubView { + @InjectView(android.R.id.message) + TextView monthTxt; + + private ViewInteractor viewInteractor; + + private @LayoutRes int layoutResId = R.layout.sub_view; + private CustomizableCalendarPresenter presenter; + public SubView(Context context) { this(context, null); } @@ -23,5 +47,41 @@ public SubView(Context context, AttributeSet attrs, int defStyleAttr) { } private void init(Context context, AttributeSet attrs) { + LayoutInflater.from(context).inflate(layoutResId, this); + ButterKnife.inject(this); + } + + @Override + public void onMonthChanged(String month) { + monthTxt.setText(month); + if (viewInteractor != null) { + viewInteractor.onSubViewBindView(this, month); + } + } + + @Override + public void refreshData() { + } + + @Override + public void setLayoutResId(@LayoutRes int layoutResId) { + this.layoutResId = layoutResId; + } + + @Override + public void injectViewInteractor(ViewInteractor viewInteractor) { + this.viewInteractor = viewInteractor; + DateTime firstMonth = AUCalendar.getInstance().getFirstMonth(); + String month = firstMonth.toString("MMMMM", Locale.getDefault()); + if (!TextUtils.isEmpty(month)) { + String formattedMonth = month.substring(0, 1).toUpperCase() + month.substring(1); + onMonthChanged(formattedMonth); + } + } + + @Override + public void injectPresenter(CustomizableCalendarPresenter presenter) { + this.presenter = presenter; + this.presenter.injectSubView(this); } -} +} \ No newline at end of file From 5368cf505ee563134db466093c03ff655e5ff307 Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 11:54:05 +0200 Subject: [PATCH 15/30] implemented MonthGridView and MonthAdapter --- .../library/adapter/MonthAdapter.java | 266 ++++++++++++++++++ .../library/components/MonthGridView.java | 93 +++++- 2 files changed, 357 insertions(+), 2 deletions(-) create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/MonthAdapter.java diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/MonthAdapter.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/MonthAdapter.java new file mode 100644 index 0000000..b45eafc --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/MonthAdapter.java @@ -0,0 +1,266 @@ +package com.francesco.furlan.customizablecalendar.library.adapter; + +import android.content.Context; +import android.graphics.Color; +import android.support.annotation.LayoutRes; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; + +import com.francesco.furlan.customizablecalendar.library.R; +import com.francesco.furlan.customizablecalendar.library.interactors.AUCalendar; +import com.francesco.furlan.customizablecalendar.library.interactors.ViewInteractor; +import com.francesco.furlan.customizablecalendar.library.model.CalendarFields; +import com.francesco.furlan.customizablecalendar.library.model.CalendarItem; +import com.francesco.furlan.customizablecalendar.library.presenter.interfeaces.CustomizableCalendarPresenter; +import com.francesco.furlan.customizablecalendar.library.utils.DateUtils; +import com.francesco.furlan.customizablecalendar.library.view.MonthView; + +import org.joda.time.DateTime; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +import io.reactivex.disposables.CompositeDisposable; + +/** + * Created by francescofurlan on 23/06/17. + */ + +public class MonthAdapter extends BaseAdapter implements MonthView { + private Context context; + private AUCalendar calendar; + private int layoutResId; + private List days; + private ViewInteractor viewInteractor; + + private DateTime currentMonth; + private DateTime firstSelectedDay; + private DateTime lastSelectedDay; + private boolean multipleSelection; + private int firstDayOfWeek; + + private CompositeDisposable subscriptions; + + public MonthAdapter(Context context) { + this.context = context; + this.subscriptions = new CompositeDisposable(); + this.calendar = AUCalendar.getInstance(); + this.layoutResId = R.layout.calendar_cell; + initFromCalendar(); + subscribe(); + } + + private void initFromCalendar() { + currentMonth = calendar.getCurrentMonth().withDayOfMonth(1).withMillisOfDay(0); + + firstSelectedDay = calendar.getFirstSelectedDay(); + if (firstSelectedDay != null) { + firstSelectedDay = firstSelectedDay.withMillisOfDay(0); + } + lastSelectedDay = calendar.getLastSelectedDay(); + if (lastSelectedDay != null) { + lastSelectedDay = lastSelectedDay.withMillisOfDay(0); + } + multipleSelection = calendar.isMultipleSelectionEnabled(); + firstDayOfWeek = calendar.getFirstDayOfWeek(); + } + + @Override + public int getCount() { + return days.size(); + } + + @Override + public Object getItem(int position) { + return days.get(position); + } + + @Override + public long getItemId(int position) { + final CalendarItem item = days.get(position); + if (item != null) { + return days.get(position).getId(); + } + return -1; + } + + @Override + public View getView(int position, View view, ViewGroup parent) { + if (view == null) { + LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + view = inflater.inflate(layoutResId, null); + } + + final CalendarItem currentItem = days.get(position); + + final TextView dayView = (TextView) view.findViewById(android.R.id.title); + final View background = view.findViewById(android.R.id.background); + final View startSelectionView = view.findViewById(android.R.id.startSelectingText); + final View endSelectionView = view.findViewById(android.R.id.stopSelectingText); + + startSelectionView.setVisibility(View.GONE); + endSelectionView.setVisibility(View.GONE); + + if (currentItem == null) { + background.setBackground(null); + dayView.setText(null); + } else if (currentItem.compareTo(calendar.getFirstMonth().withMillisOfDay(0)) < 0) { + currentItem.setSelectable(false); + background.setBackground(null); + dayView.setTextColor(Color.BLACK); + dayView.setText(currentItem.getDayString()); + dayView.setAlpha(0.6f); + } else { + currentItem.setSelectable(true); + dayView.setAlpha(1f); + Integer backgroundResource = null; + if (firstSelectedDay != null) { + int startSelectedCompared = currentItem.compareTo(firstSelectedDay); + if (!multipleSelection) { + if (startSelectedCompared == 0) { + backgroundResource = R.drawable.empty_circle; + } + } else if (startSelectedCompared == 0) { + if (lastSelectedDay == null || lastSelectedDay.equals(currentItem.getDateTime())) { + backgroundResource = R.drawable.circle; + } else { + backgroundResource = R.drawable.left_rounded_rectangle; + endSelectionView.setVisibility(View.VISIBLE); + } + } else if (startSelectedCompared > 0 && lastSelectedDay != null) { + int endSelectedCompared = currentItem.compareTo(lastSelectedDay); + if (endSelectedCompared == 0) { + backgroundResource = R.drawable.right_rounded_rectangle; + startSelectionView.setVisibility(View.VISIBLE); + } else if (endSelectedCompared < 0) { + backgroundResource = R.drawable.rectangle; + startSelectionView.setVisibility(View.VISIBLE); + endSelectionView.setVisibility(View.VISIBLE); + } + } + } + + int color = Color.BLACK; + if (backgroundResource != null) { + background.setBackgroundResource(backgroundResource); + if (multipleSelection) { + color = Color.WHITE; + } + } else { + background.setBackground(null); + } + + dayView.setTextColor(color); + dayView.setText(currentItem.getDayString()); + } + + return view; + } + + @Override + public void refreshData() { + refreshDays(); + } + + @Override + public void setLayoutResId(@LayoutRes int layoutResId) { + if (layoutResId != -1) { + this.layoutResId = layoutResId; + } + } + + @Override + public void injectViewInteractor(ViewInteractor viewInteractor) { + this.viewInteractor = viewInteractor; + } + + @Override + public void injectPresenter(CustomizableCalendarPresenter presenter) { + } + + @Override + public void setSelected(DateTime dateSelected) { + if (!multipleSelection) { + notifyFirstSelectionUpdated(dateSelected); + } else { + if (firstSelectedDay != null) { + int startSelectedCompared = dateSelected.compareTo(firstSelectedDay); + if (startSelectedCompared < 0) { + notifyFirstSelectionUpdated(dateSelected); + } else if (lastSelectedDay != null) { + int endSelectedCompared = dateSelected.compareTo(lastSelectedDay); + if ((startSelectedCompared >= 0 && endSelectedCompared < 0) || endSelectedCompared > 0) { + notifyLastSelectionUpdated(dateSelected); + } + } else { + notifyLastSelectionUpdated(dateSelected); + } + } else { + notifyFirstSelectionUpdated(dateSelected); + } + } + } + + private void notifyFirstSelectionUpdated(DateTime startSelected) { + this.firstSelectedDay = startSelected; + this.calendar.setFirstSelectedDay(startSelected); + } + + private void notifyLastSelectionUpdated(DateTime endSelected) { + this.lastSelectedDay = endSelected; + this.calendar.setLastSelectedDay(endSelected); + } + + @Override + public final void refreshDays() { + final int empties; + final int year = currentMonth.getYear(); + final int month = currentMonth.getMonthOfYear(); + final int firstDayOfMonth = currentMonth.getDayOfWeek() + 1; + final int lastDayOfMonth = DateUtils.getDaysInMonth(month - 1, year); + + // default days calculation + if (firstDayOfMonth == firstDayOfWeek) { + empties = 0; + } else if (firstDayOfMonth < firstDayOfWeek) { + empties = Calendar.SATURDAY - (firstDayOfWeek - 1); + } else { + empties = firstDayOfMonth - firstDayOfWeek; + } + + int totDays = lastDayOfMonth + empties; + days = new ArrayList<>(totDays); + + for (int day = 1, position = 1; position < totDays; position++) { + if (position > empties) { + days.add(new CalendarItem(day++, month, year)); + } else { + days.add(null); + } + } + notifyDataSetChanged(); + } + + private void subscribe() { + subscriptions.add( + calendar.observeChangesOnCalendar() + .subscribe(changeSet -> { + if (changeSet.isFieldChanged(CalendarFields.FIRST_DAY_OF_WEEK) + || changeSet.isFieldChanged(CalendarFields.FIRST_SELECTED_DAY) + || changeSet.isFieldChanged(CalendarFields.LAST_SELECTED_DAY)) { + initFromCalendar(); + refreshDays(); + } + }) + ); + } + + @Override + public void unsubscribe() { + subscriptions.clear(); + } +} \ No newline at end of file diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/MonthGridView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/MonthGridView.java index bfdb1b0..2edf1cb 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/MonthGridView.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/MonthGridView.java @@ -2,17 +2,37 @@ import android.content.Context; import android.content.res.TypedArray; +import android.support.annotation.LayoutRes; import android.support.annotation.Nullable; import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.widget.GridView; import android.widget.LinearLayout; import com.francesco.furlan.customizablecalendar.library.R; +import com.francesco.furlan.customizablecalendar.library.adapter.MonthAdapter; +import com.francesco.furlan.customizablecalendar.library.interactors.ViewInteractor; +import com.francesco.furlan.customizablecalendar.library.model.CalendarItem; +import com.francesco.furlan.customizablecalendar.library.presenter.interfeaces.CustomizableCalendarPresenter; +import com.francesco.furlan.customizablecalendar.library.view.BaseView; + +import org.joda.time.DateTime; /** * Created by francescofurlan on 23/06/17. */ -public class MonthGridView extends LinearLayout { +public class MonthGridView extends LinearLayout implements BaseView { + protected DateTime monthDateTime; + private MonthAdapter calendarAdapter; + private GridView calendarGrid; + private + @LayoutRes + int layoutResId = -1; + private + @LayoutRes + int dayLayoutResId = -1; + public MonthGridView(Context context) { this(context, null); } @@ -27,9 +47,78 @@ public MonthGridView(Context context, @Nullable AttributeSet attrs, int defStyle } private void init(Context context, AttributeSet attrs) { + monthDateTime = new DateTime(); + layoutResId = R.layout.calendar_view; + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomizableCalendar); if (typedArray != null) { + layoutResId = typedArray.getResourceId(R.styleable.CustomizableCalendar_month_layout, R.layout.calendar_view); typedArray.recycle(); } + + } + + @Override + public void setLayoutResId(@LayoutRes int layoutResId) { + if (layoutResId != -1) { + this.layoutResId = layoutResId; + } + } + + public void setDayLayoutResId(int dayLayoutResId) { + if (layoutResId != -1) { + this.dayLayoutResId = dayLayoutResId; + } + } + + @Override + public void injectViewInteractor(ViewInteractor viewInteractor) { + bindViews(); + calendarAdapter.injectViewInteractor(viewInteractor); + setupCalendar(); + } + + @Override + public void injectPresenter(CustomizableCalendarPresenter presenter) { + + } + + private void bindViews() { + final LinearLayout calendarLayout = (LinearLayout) LayoutInflater.from(getContext()).inflate(layoutResId, this); + calendarGrid = (GridView) calendarLayout.findViewById(android.R.id.widget_frame); + calendarAdapter = new MonthAdapter(getContext()); + calendarAdapter.setLayoutResId(dayLayoutResId); + calendarAdapter.refreshDays(); + } + + private void setupCalendar() { + calendarAdapter = new MonthAdapter(getContext()); + + calendarAdapter.setLayoutResId(dayLayoutResId); + + calendarAdapter.refreshDays(); + + calendarGrid.setAdapter(calendarAdapter); + + calendarGrid.setOnItemClickListener((parent, view, position, id) -> { + Object currentObj = calendarAdapter.getItem(position); + if (currentObj != null) { + CalendarItem calendarItem = (CalendarItem) currentObj; + if (calendarItem.isSelectable()) { + calendarAdapter.setSelected(calendarItem.getDateTime()); + } + } + }); + } + + @Override + public void refreshData() { + setupCalendar(); + } + + public void unsubscribe() { + if (calendarAdapter != null) { + calendarAdapter.unsubscribe(); + } } -} +} \ No newline at end of file From 3111dfd78fe71ac3678c4a07b6da98d568edd3d0 Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 11:56:45 +0200 Subject: [PATCH 16/30] implemented CalendarRecyclerView and CalendarViewAdapter --- .../library/adapter/CalendarViewAdapter.java | 95 ++++++++++++++++ .../components/CalendarRecyclerView.java | 101 +++++++++++++++++- 2 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/CalendarViewAdapter.java diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/CalendarViewAdapter.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/CalendarViewAdapter.java new file mode 100644 index 0000000..441aeeb --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/CalendarViewAdapter.java @@ -0,0 +1,95 @@ +package com.francesco.furlan.customizablecalendar.library.adapter; + +import android.content.Context; +import android.support.annotation.LayoutRes; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +import com.francesco.furlan.customizablecalendar.library.components.MonthGridView; +import com.francesco.furlan.customizablecalendar.library.interactors.AUCalendar; +import com.francesco.furlan.customizablecalendar.library.interactors.ViewInteractor; +import com.francesco.furlan.customizablecalendar.library.presenter.interfeaces.CustomizableCalendarPresenter; +import com.francesco.furlan.customizablecalendar.library.view.BaseView; + +/** + * Created by francescofurlan on 23/06/17. + */ + +public class CalendarViewAdapter extends RecyclerView.Adapter implements BaseView { + private Context context; + private AUCalendar calendar; + private int layoutResId = -1; + private int dayLayoutResId = -1; + private ViewInteractor viewInteractor; + + public CalendarViewAdapter(Context context) { + this.context = context; + this.calendar = AUCalendar.getInstance(); + } + + @Override + public int getItemCount() { + return calendar.getMonths().size(); + } + + @Override + public CalendarViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View rootView; + if (layoutResId != -1) { + rootView = LayoutInflater.from(context).inflate(layoutResId, null); + } else { + MonthGridView monthGridView = new MonthGridView(context); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + monthGridView.setLayoutParams(params); + rootView = monthGridView; + } + + if (viewInteractor != null) { + viewInteractor.onMonthBindView(rootView); + } + return new CalendarViewHolder(rootView, layoutResId, dayLayoutResId, viewInteractor); + } + + @Override + public void onBindViewHolder(final CalendarViewHolder viewHolder, final int position) { + viewHolder.monthView.refreshData(); + } + + @Override + public void refreshData() { + notifyDataSetChanged(); + } + + @Override + public void setLayoutResId(@LayoutRes int layoutResId) { + this.layoutResId = layoutResId; + } + + public void setDayLayoutResId(@LayoutRes int layoutResId) { + this.dayLayoutResId = layoutResId; + } + + @Override + public void injectViewInteractor(ViewInteractor viewInteractor) { + this.viewInteractor = viewInteractor; + } + + @Override + public void injectPresenter(CustomizableCalendarPresenter presenter) { + } + + static class CalendarViewHolder extends RecyclerView.ViewHolder { + MonthGridView monthView; + + CalendarViewHolder(View view, int layoutResId, int dayLayoutResId, ViewInteractor viewInteractor) { + super(view); + monthView = (MonthGridView) view; + monthView.setLayoutResId(layoutResId); + monthView.setDayLayoutResId(dayLayoutResId); + monthView.injectViewInteractor(viewInteractor); + } + } +} \ No newline at end of file diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CalendarRecyclerView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CalendarRecyclerView.java index 171b299..11e28de 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CalendarRecyclerView.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CalendarRecyclerView.java @@ -1,15 +1,36 @@ package com.francesco.furlan.customizablecalendar.library.components; import android.content.Context; +import android.support.annotation.LayoutRes; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.PagerSnapHelper; import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.SnapHelper; import android.util.AttributeSet; +import android.view.View; + +import com.francesco.furlan.customizablecalendar.library.adapter.CalendarViewAdapter; +import com.francesco.furlan.customizablecalendar.library.interactors.AUCalendar; +import com.francesco.furlan.customizablecalendar.library.interactors.ViewInteractor; +import com.francesco.furlan.customizablecalendar.library.presenter.interfeaces.CustomizableCalendarPresenter; +import com.francesco.furlan.customizablecalendar.library.view.CalendarView; + +import org.joda.time.DateTime; /** * Created by francescofurlan on 23/06/17. */ -public class CalendarRecyclerView extends RecyclerView { +public class CalendarRecyclerView extends RecyclerView implements CalendarView { + private LinearLayoutManager linearLayoutManager; + private CalendarViewAdapter calendarViewAdapter; + private ViewInteractor viewInteractor; private Context context; + private CustomizableCalendarPresenter presenter; + private int currentPosition = 0; + private int prevPosition = 0; + private int detachPosition = 0; + private AUCalendar calendar; public CalendarRecyclerView(Context context) { this(context, null); @@ -26,5 +47,83 @@ public CalendarRecyclerView(Context context, AttributeSet attrs, int defStyle) { private void init(Context context) { this.context = context; + linearLayoutManager = new LinearLayoutManager(getContext()); + linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); + setLayoutManager(linearLayoutManager); + this.calendar = AUCalendar.getInstance(); + } + + @Override + public void refreshData() { + calendarViewAdapter.refreshData(); + } + + @Override + public void setLayoutResId(@LayoutRes int layoutResId) { + + } + + @Override + public void injectViewInteractor(ViewInteractor viewInteractor) { + this.viewInteractor = viewInteractor; + if (viewInteractor != null) { + viewInteractor.onCalendarBindView(this); + } + setupCalendarAdapter(); + setupCalendarScroll(); + } + + @Override + public void injectPresenter(CustomizableCalendarPresenter presenter) { + this.presenter = presenter; + this.presenter.injectCalendarView(this); + } + + private void setupCalendarAdapter() { + calendarViewAdapter = new CalendarViewAdapter(context); + calendarViewAdapter.injectViewInteractor(viewInteractor); + setAdapter(calendarViewAdapter); + } + + private void setupCalendarScroll() { + SnapHelper snapHelper = new PagerSnapHelper(); + snapHelper.attachToRecyclerView(this); + + addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() { + @Override + public void onChildViewAttachedToWindow(View view) { + prevPosition = currentPosition; + currentPosition = getChildAdapterPosition(view); + updateCurrentMonth(); + MonthGridView monthGridView = (MonthGridView) view; + monthGridView.refreshData(); + } + + @Override + public void onChildViewDetachedFromWindow(View view) { + MonthGridView monthGridView = (MonthGridView) view; + detachPosition = getChildAdapterPosition(view); + if (detachPosition == currentPosition) { + currentPosition = prevPosition; + updateCurrentMonth(); + } + monthGridView.unsubscribe(); + } + }); + } + + private void updateCurrentMonth() { + DateTime currentMonth = calendar.getMonths().get(currentPosition); + calendar.setCurrentMonth(currentMonth); + } + + @Override + public void setMonthLayoutResId(@LayoutRes int layoutResId) { + calendarViewAdapter.setLayoutResId(layoutResId); + } + + @Override + public void setDayLayoutResId(@LayoutRes int layoutResId) { + calendarViewAdapter.setDayLayoutResId(layoutResId); } } \ No newline at end of file From 0a503091279b50369bd316ec054451c5a57c284a Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 11:57:26 +0200 Subject: [PATCH 17/30] made MonthAdapter customizable --- .../library/adapter/MonthAdapter.java | 194 ++++++++++-------- 1 file changed, 114 insertions(+), 80 deletions(-) diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/MonthAdapter.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/MonthAdapter.java index b45eafc..f5d6fc7 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/MonthAdapter.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/MonthAdapter.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.List; +import java.util.Locale; import io.reactivex.disposables.CompositeDisposable; @@ -97,65 +98,69 @@ public View getView(int position, View view, ViewGroup parent) { final CalendarItem currentItem = days.get(position); - final TextView dayView = (TextView) view.findViewById(android.R.id.title); - final View background = view.findViewById(android.R.id.background); - final View startSelectionView = view.findViewById(android.R.id.startSelectingText); - final View endSelectionView = view.findViewById(android.R.id.stopSelectingText); - - startSelectionView.setVisibility(View.GONE); - endSelectionView.setVisibility(View.GONE); - - if (currentItem == null) { - background.setBackground(null); - dayView.setText(null); - } else if (currentItem.compareTo(calendar.getFirstMonth().withMillisOfDay(0)) < 0) { - currentItem.setSelectable(false); - background.setBackground(null); - dayView.setTextColor(Color.BLACK); - dayView.setText(currentItem.getDayString()); - dayView.setAlpha(0.6f); + if (viewInteractor != null && viewInteractor.hasImplementedMonthCellBinding()) { + viewInteractor.onMonthCellBindView(view); } else { - currentItem.setSelectable(true); - dayView.setAlpha(1f); - Integer backgroundResource = null; - if (firstSelectedDay != null) { - int startSelectedCompared = currentItem.compareTo(firstSelectedDay); - if (!multipleSelection) { - if (startSelectedCompared == 0) { - backgroundResource = R.drawable.empty_circle; - } - } else if (startSelectedCompared == 0) { - if (lastSelectedDay == null || lastSelectedDay.equals(currentItem.getDateTime())) { - backgroundResource = R.drawable.circle; - } else { - backgroundResource = R.drawable.left_rounded_rectangle; - endSelectionView.setVisibility(View.VISIBLE); - } - } else if (startSelectedCompared > 0 && lastSelectedDay != null) { - int endSelectedCompared = currentItem.compareTo(lastSelectedDay); - if (endSelectedCompared == 0) { - backgroundResource = R.drawable.right_rounded_rectangle; - startSelectionView.setVisibility(View.VISIBLE); - } else if (endSelectedCompared < 0) { - backgroundResource = R.drawable.rectangle; - startSelectionView.setVisibility(View.VISIBLE); - endSelectionView.setVisibility(View.VISIBLE); + final TextView dayView = (TextView) view.findViewById(android.R.id.title); + final View background = view.findViewById(android.R.id.background); + final View startSelectionView = view.findViewById(android.R.id.startSelectingText); + final View endSelectionView = view.findViewById(android.R.id.stopSelectingText); + + startSelectionView.setVisibility(View.GONE); + endSelectionView.setVisibility(View.GONE); + + if (currentItem == null) { + background.setBackground(null); + dayView.setText(null); + } else if (currentItem.compareTo(calendar.getFirstMonth().withMillisOfDay(0)) < 0) { + currentItem.setSelectable(false); + background.setBackground(null); + dayView.setTextColor(Color.BLACK); + dayView.setText(currentItem.getDayString()); + dayView.setAlpha(0.6f); + } else { + currentItem.setSelectable(true); + dayView.setAlpha(1f); + Integer backgroundResource = null; + if (firstSelectedDay != null) { + int startSelectedCompared = currentItem.compareTo(firstSelectedDay); + if (!multipleSelection) { + if (startSelectedCompared == 0) { + backgroundResource = R.drawable.empty_circle; + } + } else if (startSelectedCompared == 0) { + if (lastSelectedDay == null || lastSelectedDay.equals(currentItem.getDateTime())) { + backgroundResource = R.drawable.circle; + } else { + backgroundResource = R.drawable.left_rounded_rectangle; + endSelectionView.setVisibility(View.VISIBLE); + } + } else if (startSelectedCompared > 0 && lastSelectedDay != null) { + int endSelectedCompared = currentItem.compareTo(lastSelectedDay); + if (endSelectedCompared == 0) { + backgroundResource = R.drawable.right_rounded_rectangle; + startSelectionView.setVisibility(View.VISIBLE); + } else if (endSelectedCompared < 0) { + backgroundResource = R.drawable.rectangle; + startSelectionView.setVisibility(View.VISIBLE); + endSelectionView.setVisibility(View.VISIBLE); + } } } - } - int color = Color.BLACK; - if (backgroundResource != null) { - background.setBackgroundResource(backgroundResource); - if (multipleSelection) { - color = Color.WHITE; + int color = Color.BLACK; + if (backgroundResource != null) { + background.setBackgroundResource(backgroundResource); + if (multipleSelection) { + color = Color.WHITE; + } + } else { + background.setBackground(null); } - } else { - background.setBackground(null); - } - dayView.setTextColor(color); - dayView.setText(currentItem.getDayString()); + dayView.setTextColor(color); + dayView.setText(currentItem.getDayString()); + } } return view; @@ -182,27 +187,51 @@ public void injectViewInteractor(ViewInteractor viewInteractor) { public void injectPresenter(CustomizableCalendarPresenter presenter) { } + /** + * Select the day specified if multiple selection mode is not enabled, + * otherwise adjust the ends of the selection: + * first end will be set if the day specified is before the first end; + * last end will be set if the day specified is after the last end; + * + * @param dateSelected a DateTime object that represents the day that + * should be selected + */ @Override public void setSelected(DateTime dateSelected) { - if (!multipleSelection) { - notifyFirstSelectionUpdated(dateSelected); - } else { - if (firstSelectedDay != null) { - int startSelectedCompared = dateSelected.compareTo(firstSelectedDay); - if (startSelectedCompared < 0) { + if (viewInteractor != null && viewInteractor.hasImplementedSelection()) { + int itemSelected = viewInteractor.setSelected(multipleSelection, dateSelected); + switch (itemSelected) { + case 0: notifyFirstSelectionUpdated(dateSelected); - } else if (lastSelectedDay != null) { - int endSelectedCompared = dateSelected.compareTo(lastSelectedDay); - if ((startSelectedCompared >= 0 && endSelectedCompared < 0) || endSelectedCompared > 0) { + break; + case 1: + notifyLastSelectionUpdated(dateSelected); + break; + default: + return; + } + } else { + if (!multipleSelection) { + notifyFirstSelectionUpdated(dateSelected); + } else { + if (firstSelectedDay != null) { + int startSelectedCompared = dateSelected.compareTo(firstSelectedDay); + if (startSelectedCompared < 0) { + notifyFirstSelectionUpdated(dateSelected); + } else if (lastSelectedDay != null) { + int endSelectedCompared = dateSelected.compareTo(lastSelectedDay); + if ((startSelectedCompared >= 0 && endSelectedCompared < 0) || endSelectedCompared > 0) { + notifyLastSelectionUpdated(dateSelected); + } + } else { notifyLastSelectionUpdated(dateSelected); } } else { - notifyLastSelectionUpdated(dateSelected); + notifyFirstSelectionUpdated(dateSelected); } - } else { - notifyFirstSelectionUpdated(dateSelected); } } + notifyDataSetChanged(); } private void notifyFirstSelectionUpdated(DateTime startSelected) { @@ -221,27 +250,32 @@ public final void refreshDays() { final int year = currentMonth.getYear(); final int month = currentMonth.getMonthOfYear(); final int firstDayOfMonth = currentMonth.getDayOfWeek() + 1; - final int lastDayOfMonth = DateUtils.getDaysInMonth(month - 1, year); + final int lastDayOfMonth = DateUtils.getDaysInMonth(month-1, year); - // default days calculation - if (firstDayOfMonth == firstDayOfWeek) { - empties = 0; - } else if (firstDayOfMonth < firstDayOfWeek) { - empties = Calendar.SATURDAY - (firstDayOfWeek - 1); + if (viewInteractor != null && viewInteractor.hasImplementedDayCalculation()) { + days = viewInteractor.calculateDays(year, month, firstDayOfMonth, lastDayOfMonth); } else { - empties = firstDayOfMonth - firstDayOfWeek; - } + // default days calculation + if (firstDayOfMonth == firstDayOfWeek) { + empties = 0; + } else if (firstDayOfMonth < firstDayOfWeek) { + empties = Calendar.SATURDAY - (firstDayOfWeek - 1); + } else { + empties = firstDayOfMonth - firstDayOfWeek; + } - int totDays = lastDayOfMonth + empties; - days = new ArrayList<>(totDays); + int totDays = lastDayOfMonth + empties; + days = new ArrayList<>(totDays); - for (int day = 1, position = 1; position < totDays; position++) { - if (position > empties) { - days.add(new CalendarItem(day++, month, year)); - } else { - days.add(null); + for (int day = 1, position = 1; position < totDays; position++) { + if (position > empties) { + days.add(new CalendarItem(day++, month, year)); + } else { + days.add(null); + } } } + notifyDataSetChanged(); } From 0047309c66e299ee6123fca7667ebb7fe8193f84 Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 11:58:18 +0200 Subject: [PATCH 18/30] added resources --- library/src/main/res/drawable/circle.xml | 20 +++++++++++ .../res/drawable/left_rounded_rectangle.xml | 7 ++++ library/src/main/res/drawable/rectangle.xml | 4 +++ .../res/drawable/right_rounded_rectangle.xml | 7 ++++ .../main/res/layout/customizable_calendar.xml | 33 +++++++++++++++++++ library/src/main/res/values/colors.xml | 5 +++ library/src/main/res/values/dimens.xml | 4 +++ 7 files changed, 80 insertions(+) create mode 100644 library/src/main/res/drawable/circle.xml create mode 100644 library/src/main/res/drawable/left_rounded_rectangle.xml create mode 100644 library/src/main/res/drawable/rectangle.xml create mode 100644 library/src/main/res/drawable/right_rounded_rectangle.xml create mode 100644 library/src/main/res/layout/customizable_calendar.xml create mode 100644 library/src/main/res/values/colors.xml create mode 100644 library/src/main/res/values/dimens.xml diff --git a/library/src/main/res/drawable/circle.xml b/library/src/main/res/drawable/circle.xml new file mode 100644 index 0000000..80b2d78 --- /dev/null +++ b/library/src/main/res/drawable/circle.xml @@ -0,0 +1,20 @@ + + + + + + + + \ No newline at end of file diff --git a/library/src/main/res/drawable/left_rounded_rectangle.xml b/library/src/main/res/drawable/left_rounded_rectangle.xml new file mode 100644 index 0000000..3b1868d --- /dev/null +++ b/library/src/main/res/drawable/left_rounded_rectangle.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/library/src/main/res/drawable/rectangle.xml b/library/src/main/res/drawable/rectangle.xml new file mode 100644 index 0000000..977ff60 --- /dev/null +++ b/library/src/main/res/drawable/rectangle.xml @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/library/src/main/res/drawable/right_rounded_rectangle.xml b/library/src/main/res/drawable/right_rounded_rectangle.xml new file mode 100644 index 0000000..31798f0 --- /dev/null +++ b/library/src/main/res/drawable/right_rounded_rectangle.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/library/src/main/res/layout/customizable_calendar.xml b/library/src/main/res/layout/customizable_calendar.xml new file mode 100644 index 0000000..aaf1fa0 --- /dev/null +++ b/library/src/main/res/layout/customizable_calendar.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/library/src/main/res/values/colors.xml b/library/src/main/res/values/colors.xml new file mode 100644 index 0000000..7491ed1 --- /dev/null +++ b/library/src/main/res/values/colors.xml @@ -0,0 +1,5 @@ + + + #3F51B5 + #303F9F + \ No newline at end of file diff --git a/library/src/main/res/values/dimens.xml b/library/src/main/res/values/dimens.xml new file mode 100644 index 0000000..dc09b04 --- /dev/null +++ b/library/src/main/res/values/dimens.xml @@ -0,0 +1,4 @@ + + + 240dp + \ No newline at end of file From c985a5c9a7618f7cc723974378e3aa5b697909f6 Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 11:59:04 +0200 Subject: [PATCH 19/30] implemented CustomizableCalendar and CustomizableCalendarPresenter --- .../components/CustomizableCalendar.java | 65 +++++++- .../CustomizableCalendarPresenterImpl.java | 150 ++++++++++++++++++ 2 files changed, 211 insertions(+), 4 deletions(-) create mode 100644 library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/implementations/CustomizableCalendarPresenterImpl.java diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CustomizableCalendar.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CustomizableCalendar.java index 59019db..0d5057a 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CustomizableCalendar.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CustomizableCalendar.java @@ -2,19 +2,28 @@ import android.content.Context; import android.content.res.TypedArray; +import android.os.Bundle; +import android.os.Parcelable; import android.support.annotation.Nullable; import android.util.AttributeSet; +import android.view.LayoutInflater; import android.widget.LinearLayout; import com.francesco.furlan.customizablecalendar.library.R; +import com.francesco.furlan.customizablecalendar.library.interactors.ViewInteractor; +import com.francesco.furlan.customizablecalendar.library.presenter.implementations.CustomizableCalendarPresenterImpl; +import com.francesco.furlan.customizablecalendar.library.presenter.interfeaces.CustomizableCalendarPresenter; +import com.francesco.furlan.customizablecalendar.library.view.CustomizableCalendarView; +import com.google.gson.Gson; +import butterknife.ButterKnife; import butterknife.InjectView; /** * Created by francescofurlan on 23/06/17. */ -public class CustomizableCalendar extends LinearLayout { +public class CustomizableCalendar extends LinearLayout implements CustomizableCalendarView { @InjectView(android.R.id.primary) HeaderView headerView; @@ -28,6 +37,10 @@ public class CustomizableCalendar extends LinearLayout { @InjectView(android.R.id.content) CalendarRecyclerView calendarRecyclerView; + CustomizableCalendarPresenter presenter; + + private int layoutResId = -1; + public CustomizableCalendar(Context context) { this(context, null); } @@ -42,9 +55,53 @@ public CustomizableCalendar(Context context, @Nullable AttributeSet attrs, int d } private void init(Context context, AttributeSet attrs, int defStyleAttr) { - TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomizableCalendar); - if (typedArray != null) { - typedArray.recycle(); + if (presenter == null) { + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomizableCalendar); + presenter = new CustomizableCalendarPresenterImpl(); + presenter.setView(this); + layoutResId = R.layout.customizable_calendar; + if (typedArray != null) { + layoutResId = typedArray.getResourceId(R.styleable.CustomizableCalendar_layout, R.layout.customizable_calendar); + typedArray.recycle(); + } + + LayoutInflater.from(context).inflate(layoutResId, this); + ButterKnife.inject(this); } } + + public CustomizableCalendarPresenter getPresenter() { + return presenter; + } + + @Override + public void injectViewInteractor(ViewInteractor viewInteractor) { + viewInteractor.onCustomizableCalendarBindView(this); + presenter.injectViewInteractor(viewInteractor); + headerView.injectPresenter(presenter); + calendarRecyclerView.injectPresenter(presenter); + subView.injectPresenter(presenter); + weekDaysView.injectPresenter(presenter); + } + + @Override + public void injectPresenter(CustomizableCalendarPresenter presenter) { + this.presenter = presenter; + presenter.setView(this); + } + + @Override + public void onCurrentMonthChanged(String month) { + subView.onMonthChanged(month); + } + + @Override + public void refreshData() { + + } + + @Override + public void setLayoutResId(int layoutResId) { + this.layoutResId = layoutResId; + } } \ No newline at end of file diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/implementations/CustomizableCalendarPresenterImpl.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/implementations/CustomizableCalendarPresenterImpl.java new file mode 100644 index 0000000..e7a0cf8 --- /dev/null +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/implementations/CustomizableCalendarPresenterImpl.java @@ -0,0 +1,150 @@ +package com.francesco.furlan.customizablecalendar.library.presenter.implementations; + +import android.support.annotation.LayoutRes; +import android.text.TextUtils; +import android.view.View; + +import com.francesco.furlan.customizablecalendar.library.interactors.AUCalendar; +import com.francesco.furlan.customizablecalendar.library.interactors.ViewInteractor; +import com.francesco.furlan.customizablecalendar.library.model.CalendarFields; +import com.francesco.furlan.customizablecalendar.library.presenter.interfeaces.CustomizableCalendarPresenter; +import com.francesco.furlan.customizablecalendar.library.view.CalendarView; +import com.francesco.furlan.customizablecalendar.library.view.CustomizableCalendarView; +import com.francesco.furlan.customizablecalendar.library.view.HeaderView; +import com.francesco.furlan.customizablecalendar.library.view.SubView; +import com.francesco.furlan.customizablecalendar.library.view.WeekDaysView; + +import org.joda.time.DateTime; + +import java.util.Locale; + +import io.reactivex.disposables.CompositeDisposable; + +/** + * Created by francescofurlan on 23/06/17. + */ + +public class CustomizableCalendarPresenterImpl implements CustomizableCalendarPresenter { + private AUCalendar calendar; + private CalendarView calendarView; + private HeaderView headerView; + private SubView subView; + private WeekDaysView weekDaysView; + private ViewInteractor viewInteractor; + private CustomizableCalendarView view; + private CompositeDisposable subscriptions = new CompositeDisposable(); + + @Override + public void injectViewInteractor(ViewInteractor viewInteractor) { + this.viewInteractor = viewInteractor; + } + + @Override + public void setLayoutResId(@LayoutRes int layoutResId) { + view.setLayoutResId(layoutResId); + } + + @Override + public void setView(CustomizableCalendarView view) { + this.view = view; + if (viewInteractor != null) { + view.injectViewInteractor(viewInteractor); + } + calendar = AUCalendar.getInstance(); + subscriptions.add( + calendar.observeChangesOnCalendar() + .subscribe(changeSet -> { + if (changeSet.isFieldChanged(CalendarFields.CURRENT_MONTH)) { + onCurrentMonthChanged(calendar.getCurrentMonth()); + } + if (changeSet.isFieldChanged(CalendarFields.FIRST_DAY_OF_WEEK)) { + if (weekDaysView != null) { + weekDaysView.onFirstDayOfWeek(calendar.getFirstDayOfWeek()); + } + if (calendarView != null) { + calendarView.refreshData(); + } + } + }) + ); + } + + @Override + public void onBindView(View rootView) { + viewInteractor.onCustomizableCalendarBindView(rootView); + } + + private void onCurrentMonthChanged(DateTime currentMonth) { + String month = currentMonth.toString("MMMMM", Locale.getDefault()); + if (view != null && !TextUtils.isEmpty(month)) { + String formattedMonth = month.substring(0, 1).toUpperCase() + month.substring(1); + view.onCurrentMonthChanged(formattedMonth); + } + } + + @Override + public void injectCalendarView(CalendarView calendarView) { + this.calendarView = calendarView; + this.calendarView.injectViewInteractor(viewInteractor); + } + + @Override + public void injectHeaderView(HeaderView headerView) { + this.headerView = headerView; + this.headerView.injectViewInteractor(viewInteractor); + } + + @Override + public void injectSubView(SubView subView) { + this.subView = subView; + this.subView.injectViewInteractor(viewInteractor); + } + + @Override + public void injectWeekDaysView(WeekDaysView weekDaysView) { + this.weekDaysView = weekDaysView; + this.weekDaysView.injectViewInteractor(viewInteractor); + } + + @Override + public void setCustomizableCalendarLayoutResId(@LayoutRes int resId) { + if (view != null) { + view.setLayoutResId(resId); + } + } + + @Override + public void setHeaderLayoutResId(@LayoutRes int resId) { + if (headerView != null) { + headerView.setLayoutResId(resId); + } + } + + @Override + public void setWeekDayResId(@LayoutRes int resId) { + if (weekDaysView != null) { + weekDaysView.setLayoutResId(resId); + } + } + + @Override + public void setSubViewResId(@LayoutRes int resId) { + if (subView != null) { + subView.setLayoutResId(resId); + } + } + + @Override + public void setMonthResId(@LayoutRes int resId) { + if (calendarView != null) { + calendarView.setMonthLayoutResId(resId); + } + } + + @Override + public void setDayResId(@LayoutRes int resId) { + if (calendarView != null) { + calendarView.setDayLayoutResId(resId); + } + } +} From 6694aba9450647202a8bc73a826b03663694cd99 Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 12:01:00 +0200 Subject: [PATCH 20/30] removed useless imports --- .../library/components/CustomizableCalendar.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CustomizableCalendar.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CustomizableCalendar.java index 0d5057a..dd5811d 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CustomizableCalendar.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CustomizableCalendar.java @@ -2,8 +2,6 @@ import android.content.Context; import android.content.res.TypedArray; -import android.os.Bundle; -import android.os.Parcelable; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.LayoutInflater; @@ -14,7 +12,6 @@ import com.francesco.furlan.customizablecalendar.library.presenter.implementations.CustomizableCalendarPresenterImpl; import com.francesco.furlan.customizablecalendar.library.presenter.interfeaces.CustomizableCalendarPresenter; import com.francesco.furlan.customizablecalendar.library.view.CustomizableCalendarView; -import com.google.gson.Gson; import butterknife.ButterKnife; import butterknife.InjectView; From fcbd029dfaad499f7b64b568e1f8698dd0661cc8 Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 12:02:48 +0200 Subject: [PATCH 21/30] updated layouts --- app/src/main/res/layout/activity_main.xml | 7 +++++ app/src/main/res/layout/c_calendar.xml | 33 +++++++++++++++++++++++ app/src/main/res/values/styles.xml | 11 ++++++++ library/.gitignore | 1 + 4 files changed, 52 insertions(+) create mode 100644 app/src/main/res/layout/c_calendar.xml create mode 100644 app/src/main/res/values/styles.xml create mode 100644 library/.gitignore diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 0d9cf32..88f0aae 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,7 +1,14 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/c_calendar.xml b/app/src/main/res/layout/c_calendar.xml new file mode 100644 index 0000000..aaf1fa0 --- /dev/null +++ b/app/src/main/res/layout/c_calendar.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..5885930 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/library/.gitignore b/library/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/library/.gitignore @@ -0,0 +1 @@ +/build From 517d35a7e1b191fa731987423cb264d9cefe1549 Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 12:03:37 +0200 Subject: [PATCH 22/30] implemented sample --- .../CalendarViewInteractor.java | 114 ++++++++++++++++++ .../customizablecalendar/MainActivity.java | 53 +++++++- app/src/main/res/layout/calendar_header.xml | 80 ++++++++++++ app/src/main/res/values/strings.xml | 3 + 4 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/com/francesco/furlan/customizablecalendar/CalendarViewInteractor.java create mode 100644 app/src/main/res/layout/calendar_header.xml diff --git a/app/src/main/java/com/francesco/furlan/customizablecalendar/CalendarViewInteractor.java b/app/src/main/java/com/francesco/furlan/customizablecalendar/CalendarViewInteractor.java new file mode 100644 index 0000000..afe1125 --- /dev/null +++ b/app/src/main/java/com/francesco/furlan/customizablecalendar/CalendarViewInteractor.java @@ -0,0 +1,114 @@ +package com.francesco.furlan.customizablecalendar; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.francesco.furlan.customizablecalendar.library.adapter.WeekDaysViewAdapter; +import com.francesco.furlan.customizablecalendar.library.interactors.ViewInteractor; +import com.francesco.furlan.customizablecalendar.library.model.Calendar; +import com.francesco.furlan.customizablecalendar.library.model.CalendarItem; + +import org.joda.time.DateTime; + +import java.util.List; + +/** + * Created by francescofurlan on 03/07/17. + */ + +public class CalendarViewInteractor implements ViewInteractor { + private Context context; + private Calendar calendar; + private TextView firstDaySelectedTxt; + private TextView lastDaySelectedTxt; + + CalendarViewInteractor(Context context) { + this.context = context; + } + + @Override + public void onCustomizableCalendarBindView(View view) { + + } + + @Override + public void onHeaderBindView(ViewGroup view) { + RelativeLayout layout = (RelativeLayout) LayoutInflater.from(context).inflate(R.layout.calendar_header, view); + firstDaySelectedTxt = (TextView) layout.findViewById(R.id.first_day_selected); + lastDaySelectedTxt = (TextView) layout.findViewById(R.id.last_day_selected); + updateCalendar(calendar); + } + + @Override + public void onWeekDaysBindView(View view) { + + } + + @Override + public void onWeekDayBindView(WeekDaysViewAdapter.WeekDayVH holder, String weekDay) { + + } + + @Override + public void onSubViewBindView(View view, String month) { + + } + + @Override + public void onCalendarBindView(View view) { + + } + + @Override + public void onMonthBindView(View view) { + + } + + @Override + public void onMonthCellBindView(View view) { + + } + + @Override + public boolean hasImplementedDayCalculation() { + return false; + } + + @Override + public List calculateDays(int year, int month, int firstDayOfMonth, int lastDayOfMonth) { + return null; + } + + @Override + public boolean hasImplementedSelection() { + return false; + } + + @Override + public int setSelected(boolean multipleSelection, DateTime dateSelected) { + return -1; + } + + @Override + public boolean hasImplementedMonthCellBinding() { + return false; + } + + void updateCalendar(Calendar calendar) { + this.calendar = calendar; + if (firstDaySelectedTxt != null && lastDaySelectedTxt != null) { + DateTime firstDate = calendar.getFirstSelectedDay(); + DateTime lastDate = calendar.getLastSelectedDay(); + if (firstDate != null) { + firstDaySelectedTxt.setText(firstDate.toString("dd MMMMM yyyy")); + } + if (lastDate != null) { + lastDaySelectedTxt.setText(lastDate.toString("dd MMMMM yyyy")); + } + } + } +} diff --git a/app/src/main/java/com/francesco/furlan/customizablecalendar/MainActivity.java b/app/src/main/java/com/francesco/furlan/customizablecalendar/MainActivity.java index 715b94b..47b442e 100644 --- a/app/src/main/java/com/francesco/furlan/customizablecalendar/MainActivity.java +++ b/app/src/main/java/com/francesco/furlan/customizablecalendar/MainActivity.java @@ -3,12 +3,63 @@ import android.os.Bundle; import android.support.v7.app.AppCompatActivity; +import com.francesco.furlan.customizablecalendar.library.components.CustomizableCalendar; +import com.francesco.furlan.customizablecalendar.library.interactors.AUCalendar; +import com.francesco.furlan.customizablecalendar.library.model.Calendar; + +import org.joda.time.DateTime; + +import butterknife.ButterKnife; +import butterknife.InjectView; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.functions.Consumer; + public class MainActivity extends AppCompatActivity { + @InjectView(R.id.view_month) + CustomizableCalendar customizableCalendar; + + private CompositeDisposable subscriptions; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); + ButterKnife.inject(this); + subscriptions = new CompositeDisposable(); + updateData(); } -} + private void updateData() { + // setting up first and last month that must be showed in the calendar + DateTime firstMonth = new DateTime().withDayOfMonth(1); + DateTime lastMonth = new DateTime().plusMonths(3).withDayOfMonth(1); + + // create the Calendar obj and setting it up with some configs like: + // - first selected day + // - last selected day + // - multiple selection + final Calendar calendar = new Calendar(firstMonth, lastMonth); + calendar.setFirstSelectedDay(new DateTime().plusDays(4)); + calendar.setLastSelectedDay(new DateTime().plusDays(6)); + calendar.setMultipleSelection(true); + + // create a CalendarViewInteractor obj needed to interact with the CustomizableCalendar + final CalendarViewInteractor calendarViewInteractor = new CalendarViewInteractor(getBaseContext()); + + // create the AUCalendar obj and observes changes on it + AUCalendar auCalendar = AUCalendar.getInstance(calendar); + calendarViewInteractor.updateCalendar(calendar); + subscriptions.add( + auCalendar.observeChangesOnCalendar().subscribe(new Consumer() { + @Override + public void accept(AUCalendar.ChangeSet changeSet) throws Exception { + calendarViewInteractor.updateCalendar(calendar); + } + }) + ); + + // inject (set) the calendarViewInteractor to the CustomizableCalendar + customizableCalendar.injectViewInteractor(calendarViewInteractor); + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/calendar_header.xml b/app/src/main/res/layout/calendar_header.xml new file mode 100644 index 0000000..170627b --- /dev/null +++ b/app/src/main/res/layout/calendar_header.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index db8b5b0..153df77 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,6 @@ CustomizableCalendar + day month year + First day selected + Last day selected From ae0333940c4c8010f070b15cd6c5b9d278b0a4f4 Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Tue, 4 Jul 2017 12:22:03 +0200 Subject: [PATCH 23/30] Reformatted code and optimized imports --- .../library/adapter/MonthAdapter.java | 3 +- .../library/adapter/WeekDaysViewAdapter.java | 27 +++--- .../library/components/WeekDaysView.java | 1 - .../library/interactors/AUCalendar.java | 94 +++++++++---------- .../library/model/Calendar.java | 2 +- library/src/main/res/layout/week_day_view.xml | 4 +- 6 files changed, 62 insertions(+), 69 deletions(-) diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/MonthAdapter.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/MonthAdapter.java index f5d6fc7..0a1b4ec 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/MonthAdapter.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/MonthAdapter.java @@ -23,7 +23,6 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.List; -import java.util.Locale; import io.reactivex.disposables.CompositeDisposable; @@ -250,7 +249,7 @@ public final void refreshDays() { final int year = currentMonth.getYear(); final int month = currentMonth.getMonthOfYear(); final int firstDayOfMonth = currentMonth.getDayOfWeek() + 1; - final int lastDayOfMonth = DateUtils.getDaysInMonth(month-1, year); + final int lastDayOfMonth = DateUtils.getDaysInMonth(month - 1, year); if (viewInteractor != null && viewInteractor.hasImplementedDayCalculation()) { days = viewInteractor.calculateDays(year, month, firstDayOfMonth, lastDayOfMonth); diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/WeekDaysViewAdapter.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/WeekDaysViewAdapter.java index 59e50fe..6e0e4e8 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/WeekDaysViewAdapter.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/WeekDaysViewAdapter.java @@ -8,15 +8,11 @@ import android.view.ViewGroup; import android.widget.TextView; -import com.francesco.furlan.customizablecalendar.library.R; import com.francesco.furlan.customizablecalendar.library.interactors.ViewInteractor; import java.util.ArrayList; import java.util.List; -import butterknife.ButterKnife; -import butterknife.InjectView; - /** * Created by francescofurlan on 28/06/17. */ @@ -54,6 +50,17 @@ public int getItemCount() { return weekDays.size(); } + public String getItem(int position) { + return weekDays.get(position); + } + + public void setClickListener(ItemClickListener clickListener) { + this.clickListener = clickListener; + } + + public interface ItemClickListener { + void onItemClick(View view, int position); + } public class WeekDayVH extends RecyclerView.ViewHolder implements View.OnClickListener { TextView weekDayTxt; @@ -71,17 +78,5 @@ public void onClick(View view) { } } } - - public String getItem(int position) { - return weekDays.get(position); - } - - public void setClickListener(ItemClickListener clickListener) { - this.clickListener = clickListener; - } - - public interface ItemClickListener { - void onItemClick(View view, int position); - } } diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/WeekDaysView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/WeekDaysView.java index 8cf83dc..001749c 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/WeekDaysView.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/WeekDaysView.java @@ -17,7 +17,6 @@ import java.text.DateFormatSymbols; import java.util.ArrayList; -import java.util.Calendar; import java.util.List; import java.util.Locale; diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/AUCalendar.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/AUCalendar.java index f39d5cd..eb8484a 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/AUCalendar.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/AUCalendar.java @@ -17,8 +17,9 @@ */ public class AUCalendar { - private Calendar calendar; private static AUCalendar AUCalendarInstance; + private Calendar calendar; + private List onChangeListenerList = new ArrayList<>(); public static AUCalendar getInstance() { if (AUCalendarInstance == null) { @@ -39,58 +40,14 @@ public DateTime getFirstMonth() { return calendar.getFirstMonth(); } - public interface ChangeSet { - List getChangedFields(); - - boolean isFieldChanged(String fieldName); - - String toString(); - } - - private class CalendarChangeSet implements ChangeSet { - private List changedFields = new ArrayList<>(); - - public void setChangedFiels(List changedFields) { - this.changedFields = changedFields; - } - - public void addChangedField(String changedField) { - this.changedFields.add(changedField); - } - - @Override - public List getChangedFields() { - return changedFields; - } - - @Override - public boolean isFieldChanged(String fieldName) { - return changedFields.contains(fieldName); - } - @Override - public String toString() { - String fieldChanges = ""; - for (String fieldChanged : changedFields) { - fieldChanges += " " + fieldChanged; - } - return fieldChanges; - } - } - - public interface CalendarObjectChangeListener { - void onChange(ChangeSet changeSet); + public Calendar getCalendar() { + return calendar; } - private List onChangeListenerList = new ArrayList<>(); - public void setCalendar(Calendar calendar) { this.calendar = calendar; } - public Calendar getCalendar() { - return calendar; - } - public Flowable observeChangesOnCalendar() { return Flowable.create((FlowableEmitter emitter) -> { CalendarObjectChangeListener objectChangeListener = emitter::onNext; @@ -172,4 +129,47 @@ public void setFirstDayOfWeek(int firstDayOfWeek) { calendar.setFirstDayOfWeek(firstDayOfWeek); emitOnChange(CalendarFields.FIRST_DAY_OF_WEEK); } + + public interface ChangeSet { + List getChangedFields(); + + boolean isFieldChanged(String fieldName); + + String toString(); + } + + public interface CalendarObjectChangeListener { + void onChange(ChangeSet changeSet); + } + + private class CalendarChangeSet implements ChangeSet { + private List changedFields = new ArrayList<>(); + + public void setChangedFiels(List changedFields) { + this.changedFields = changedFields; + } + + public void addChangedField(String changedField) { + this.changedFields.add(changedField); + } + + @Override + public List getChangedFields() { + return changedFields; + } + + @Override + public boolean isFieldChanged(String fieldName) { + return changedFields.contains(fieldName); + } + + @Override + public String toString() { + String fieldChanges = ""; + for (String fieldChanged : changedFields) { + fieldChanges += " " + fieldChanged; + } + return fieldChanges; + } + } } \ No newline at end of file diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/model/Calendar.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/model/Calendar.java index aa6c480..3e1731b 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/model/Calendar.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/model/Calendar.java @@ -23,7 +23,7 @@ public Calendar(DateTime firstMonth, DateTime lastMonth) { this.firstMonth = firstMonth; this.firstDayOfWeek = java.util.Calendar.getInstance(Locale.getDefault()).getFirstDayOfWeek(); - int startMonth = firstMonth.getMonthOfYear()+1; + int startMonth = firstMonth.getMonthOfYear() + 1; int endMonth = lastMonth.getMonthOfYear(); months = new ArrayList<>(); diff --git a/library/src/main/res/layout/week_day_view.xml b/library/src/main/res/layout/week_day_view.xml index dfb1096..6424868 100644 --- a/library/src/main/res/layout/week_day_view.xml +++ b/library/src/main/res/layout/week_day_view.xml @@ -9,7 +9,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" - android:textSize="18sp" - android:textColor="@android:color/black" /> + android:textColor="@android:color/black" + android:textSize="18sp" /> \ No newline at end of file From a939bbd79e97b62f2689cc7566dd91705bcd0353 Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Wed, 5 Jul 2017 10:10:48 +0200 Subject: [PATCH 24/30] fixed calendar cell binding --- .../library/adapter/MonthAdapter.java | 11 +++++------ .../library/interactors/ViewInteractor.java | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/MonthAdapter.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/MonthAdapter.java index 0a1b4ec..3bc2294 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/MonthAdapter.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/MonthAdapter.java @@ -90,16 +90,15 @@ public long getItemId(int position) { @Override public View getView(int position, View view, ViewGroup parent) { - if (view == null) { - LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - view = inflater.inflate(layoutResId, null); - } - final CalendarItem currentItem = days.get(position); if (viewInteractor != null && viewInteractor.hasImplementedMonthCellBinding()) { - viewInteractor.onMonthCellBindView(view); + view = viewInteractor.onMonthCellBindView(view, currentItem); } else { + if (view == null) { + LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + view = inflater.inflate(layoutResId, null); + } final TextView dayView = (TextView) view.findViewById(android.R.id.title); final View background = view.findViewById(android.R.id.background); final View startSelectionView = view.findViewById(android.R.id.startSelectingText); diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/ViewInteractor.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/ViewInteractor.java index df0c460..5bf16f7 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/ViewInteractor.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/ViewInteractor.java @@ -29,7 +29,7 @@ public interface ViewInteractor { void onMonthBindView(View view); - void onMonthCellBindView(View view); + View onMonthCellBindView(View view, CalendarItem currentItem); boolean hasImplementedDayCalculation(); From 83099bcdb783bae93eb76984abf984e3b4f59559 Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Wed, 5 Jul 2017 10:13:52 +0200 Subject: [PATCH 25/30] SubView layoutResId from xml --- .../customizablecalendar/library/components/SubView.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/SubView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/SubView.java index 6c3735c..aa4a0a2 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/SubView.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/SubView.java @@ -1,6 +1,7 @@ package com.francesco.furlan.customizablecalendar.library.components; import android.content.Context; +import android.content.res.TypedArray; import android.support.annotation.LayoutRes; import android.text.TextUtils; import android.util.AttributeSet; @@ -32,6 +33,7 @@ public class SubView extends RelativeLayout implements com.francesco.furlan.cust private @LayoutRes int layoutResId = R.layout.sub_view; private CustomizableCalendarPresenter presenter; + private Context context; public SubView(Context context) { this(context, null); @@ -47,6 +49,13 @@ public SubView(Context context, AttributeSet attrs, int defStyleAttr) { } private void init(Context context, AttributeSet attrs) { + this.context = context; + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomizableCalendar); + if (typedArray != null) { + layoutResId = typedArray.getResourceId(R.styleable.CustomizableCalendar_layout, R.layout.sub_view); + typedArray.recycle(); + } + LayoutInflater.from(context).inflate(layoutResId, this); ButterKnife.inject(this); } From 6ad05d1f3ca9bc5e71ec6f15c835dfa91900667c Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Wed, 5 Jul 2017 10:14:23 +0200 Subject: [PATCH 26/30] fixed MonthGridView --- .../library/components/MonthGridView.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/MonthGridView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/MonthGridView.java index 2edf1cb..dc0c50b 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/MonthGridView.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/MonthGridView.java @@ -26,12 +26,14 @@ public class MonthGridView extends LinearLayout implements BaseView { protected DateTime monthDateTime; private MonthAdapter calendarAdapter; private GridView calendarGrid; + private LinearLayout calendarLayout; private @LayoutRes int layoutResId = -1; private @LayoutRes int dayLayoutResId = -1; + private ViewInteractor viewInteractor; public MonthGridView(Context context) { this(context, null); @@ -73,8 +75,8 @@ public void setDayLayoutResId(int dayLayoutResId) { @Override public void injectViewInteractor(ViewInteractor viewInteractor) { + this.viewInteractor = viewInteractor; bindViews(); - calendarAdapter.injectViewInteractor(viewInteractor); setupCalendar(); } @@ -84,11 +86,8 @@ public void injectPresenter(CustomizableCalendarPresenter presenter) { } private void bindViews() { - final LinearLayout calendarLayout = (LinearLayout) LayoutInflater.from(getContext()).inflate(layoutResId, this); + calendarLayout = (LinearLayout) LayoutInflater.from(getContext()).inflate(layoutResId, this); calendarGrid = (GridView) calendarLayout.findViewById(android.R.id.widget_frame); - calendarAdapter = new MonthAdapter(getContext()); - calendarAdapter.setLayoutResId(dayLayoutResId); - calendarAdapter.refreshDays(); } private void setupCalendar() { @@ -96,6 +95,8 @@ private void setupCalendar() { calendarAdapter.setLayoutResId(dayLayoutResId); + calendarAdapter.injectViewInteractor(viewInteractor); + calendarAdapter.refreshDays(); calendarGrid.setAdapter(calendarAdapter); From c171a361e98226d9d0b44b4dd9bbeca326213639 Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Wed, 5 Jul 2017 11:00:14 +0200 Subject: [PATCH 27/30] change and notify calendar changes only if the value actually changes --- .../library/interactors/AUCalendar.java | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/AUCalendar.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/AUCalendar.java index eb8484a..1143a03 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/AUCalendar.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/AUCalendar.java @@ -81,8 +81,10 @@ public DateTime getFirstSelectedDay() { } public void setFirstSelectedDay(DateTime firstSelectedDay) { - calendar.setFirstSelectedDay(firstSelectedDay); - emitOnChange(CalendarFields.FIRST_SELECTED_DAY); + if (calendar.getFirstSelectedDay() != firstSelectedDay) { + calendar.setFirstSelectedDay(firstSelectedDay); + emitOnChange(CalendarFields.FIRST_SELECTED_DAY); + } } public DateTime getLastSelectedDay() { @@ -90,8 +92,10 @@ public DateTime getLastSelectedDay() { } public void setLastSelectedDay(DateTime lastSelectedDay) { - calendar.setLastSelectedDay(lastSelectedDay); - emitOnChange(CalendarFields.LAST_SELECTED_DAY); + if (calendar.getLastSelectedDay() != lastSelectedDay) { + calendar.setLastSelectedDay(lastSelectedDay); + emitOnChange(CalendarFields.LAST_SELECTED_DAY); + } } public DateTime getCurrentMonth() { @@ -99,8 +103,10 @@ public DateTime getCurrentMonth() { } public void setCurrentMonth(DateTime currentMonth) { - calendar.setCurrentMonth(currentMonth); - emitOnChange(CalendarFields.CURRENT_MONTH); + if (calendar.getCurrentMonth() != currentMonth) { + calendar.setCurrentMonth(currentMonth); + emitOnChange(CalendarFields.CURRENT_MONTH); + } } public List getMonths() { @@ -108,8 +114,10 @@ public List getMonths() { } public void setMonths(List months) { - calendar.setMonths(months); - emitOnChange(CalendarFields.MONTHS); + if (calendar.getMonths() != months) { + calendar.setMonths(months); + emitOnChange(CalendarFields.MONTHS); + } } public boolean isMultipleSelectionEnabled() { @@ -117,8 +125,10 @@ public boolean isMultipleSelectionEnabled() { } public void setMultipleSelection(boolean multipleSelection) { - calendar.setMultipleSelection(multipleSelection); - emitOnChange(CalendarFields.MULTIPLE_SELECTION); + if (calendar.isMultipleSelectionEnabled() != multipleSelection) { + calendar.setMultipleSelection(multipleSelection); + emitOnChange(CalendarFields.MULTIPLE_SELECTION); + } } public int getFirstDayOfWeek() { @@ -126,8 +136,10 @@ public int getFirstDayOfWeek() { } public void setFirstDayOfWeek(int firstDayOfWeek) { - calendar.setFirstDayOfWeek(firstDayOfWeek); - emitOnChange(CalendarFields.FIRST_DAY_OF_WEEK); + if (calendar.getFirstDayOfWeek() != firstDayOfWeek) { + calendar.setFirstDayOfWeek(firstDayOfWeek); + emitOnChange(CalendarFields.FIRST_DAY_OF_WEEK); + } } public interface ChangeSet { From beeebc945e854f0c06e397b3d411fb9553e1fec5 Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Wed, 5 Jul 2017 11:39:04 +0200 Subject: [PATCH 28/30] disabled LayoutInteractor: should be implemented in the next version --- .../CustomizableCalendarPresenterImpl.java | 82 +++++++++---------- .../CustomizableCalendarPresenter.java | 3 +- 2 files changed, 42 insertions(+), 43 deletions(-) diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/implementations/CustomizableCalendarPresenterImpl.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/implementations/CustomizableCalendarPresenterImpl.java index e7a0cf8..a19665c 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/implementations/CustomizableCalendarPresenterImpl.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/implementations/CustomizableCalendarPresenterImpl.java @@ -106,45 +106,45 @@ public void injectWeekDaysView(WeekDaysView weekDaysView) { this.weekDaysView.injectViewInteractor(viewInteractor); } - @Override - public void setCustomizableCalendarLayoutResId(@LayoutRes int resId) { - if (view != null) { - view.setLayoutResId(resId); - } - } - - @Override - public void setHeaderLayoutResId(@LayoutRes int resId) { - if (headerView != null) { - headerView.setLayoutResId(resId); - } - } - - @Override - public void setWeekDayResId(@LayoutRes int resId) { - if (weekDaysView != null) { - weekDaysView.setLayoutResId(resId); - } - } - - @Override - public void setSubViewResId(@LayoutRes int resId) { - if (subView != null) { - subView.setLayoutResId(resId); - } - } - - @Override - public void setMonthResId(@LayoutRes int resId) { - if (calendarView != null) { - calendarView.setMonthLayoutResId(resId); - } - } - - @Override - public void setDayResId(@LayoutRes int resId) { - if (calendarView != null) { - calendarView.setDayLayoutResId(resId); - } - } +// @Override +// public void setCustomizableCalendarLayoutResId(@LayoutRes int resId) { +// if (view != null) { +// view.setLayoutResId(resId); +// } +// } +// +// @Override +// public void setHeaderLayoutResId(@LayoutRes int resId) { +// if (headerView != null) { +// headerView.setLayoutResId(resId); +// } +// } +// +// @Override +// public void setWeekDayResId(@LayoutRes int resId) { +// if (weekDaysView != null) { +// weekDaysView.setLayoutResId(resId); +// } +// } +// +// @Override +// public void setSubViewResId(@LayoutRes int resId) { +// if (subView != null) { +// subView.setLayoutResId(resId); +// } +// } +// +// @Override +// public void setMonthResId(@LayoutRes int resId) { +// if (calendarView != null) { +// calendarView.setMonthLayoutResId(resId); +// } +// } +// +// @Override +// public void setDayResId(@LayoutRes int resId) { +// if (calendarView != null) { +// calendarView.setDayLayoutResId(resId); +// } +// } } diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/interfeaces/CustomizableCalendarPresenter.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/interfeaces/CustomizableCalendarPresenter.java index e2bf6ce..72557a9 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/interfeaces/CustomizableCalendarPresenter.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/presenter/interfeaces/CustomizableCalendarPresenter.java @@ -1,6 +1,5 @@ package com.francesco.furlan.customizablecalendar.library.presenter.interfeaces; -import com.francesco.furlan.customizablecalendar.library.interactors.LayoutInteractor; import com.francesco.furlan.customizablecalendar.library.interactors.ViewInjector; import com.francesco.furlan.customizablecalendar.library.view.CustomizableCalendarView; @@ -8,5 +7,5 @@ * Created by francescofurlan on 23/06/17. */ -public interface CustomizableCalendarPresenter extends BasePresenter, ViewInjector, LayoutInteractor { +public interface CustomizableCalendarPresenter extends BasePresenter, ViewInjector { } From 7486828d1664138ede03ec1bd051ab45f862119d Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Wed, 5 Jul 2017 12:01:41 +0200 Subject: [PATCH 29/30] =?UTF-8?q?fixed=20layoutResId=E2=80=99s=20from=20xm?= =?UTF-8?q?l?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CalendarViewInteractor.java | 4 ++-- .../library/adapter/MonthAdapter.java | 9 ++++---- .../components/CalendarRecyclerView.java | 22 +++++++++++++++++-- .../library/components/MonthGridView.java | 1 + .../library/components/WeekDaysView.java | 3 +-- library/src/main/res/values/attrs.xml | 1 - 6 files changed, 29 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/francesco/furlan/customizablecalendar/CalendarViewInteractor.java b/app/src/main/java/com/francesco/furlan/customizablecalendar/CalendarViewInteractor.java index afe1125..1e4cb4d 100644 --- a/app/src/main/java/com/francesco/furlan/customizablecalendar/CalendarViewInteractor.java +++ b/app/src/main/java/com/francesco/furlan/customizablecalendar/CalendarViewInteractor.java @@ -69,8 +69,8 @@ public void onMonthBindView(View view) { } @Override - public void onMonthCellBindView(View view) { - + public View onMonthCellBindView(View view, CalendarItem currentItem) { + return null; } @Override diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/MonthAdapter.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/MonthAdapter.java index 3bc2294..1b4c1ab 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/MonthAdapter.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/MonthAdapter.java @@ -92,13 +92,14 @@ public long getItemId(int position) { public View getView(int position, View view, ViewGroup parent) { final CalendarItem currentItem = days.get(position); + if (view == null) { + LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + view = inflater.inflate(layoutResId, null); + } + if (viewInteractor != null && viewInteractor.hasImplementedMonthCellBinding()) { view = viewInteractor.onMonthCellBindView(view, currentItem); } else { - if (view == null) { - LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - view = inflater.inflate(layoutResId, null); - } final TextView dayView = (TextView) view.findViewById(android.R.id.title); final View background = view.findViewById(android.R.id.background); final View startSelectionView = view.findViewById(android.R.id.startSelectingText); diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CalendarRecyclerView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CalendarRecyclerView.java index 11e28de..ef3a8c6 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CalendarRecyclerView.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/CalendarRecyclerView.java @@ -1,6 +1,7 @@ package com.francesco.furlan.customizablecalendar.library.components; import android.content.Context; +import android.content.res.TypedArray; import android.support.annotation.LayoutRes; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.PagerSnapHelper; @@ -9,6 +10,7 @@ import android.util.AttributeSet; import android.view.View; +import com.francesco.furlan.customizablecalendar.library.R; import com.francesco.furlan.customizablecalendar.library.adapter.CalendarViewAdapter; import com.francesco.furlan.customizablecalendar.library.interactors.AUCalendar; import com.francesco.furlan.customizablecalendar.library.interactors.ViewInteractor; @@ -31,6 +33,12 @@ public class CalendarRecyclerView extends RecyclerView implements CalendarView { private int prevPosition = 0; private int detachPosition = 0; private AUCalendar calendar; + private + @LayoutRes + int monthResId = R.layout.calendar_view; + private + @LayoutRes + int monthCellResId = R.layout.calendar_cell; public CalendarRecyclerView(Context context) { this(context, null); @@ -42,11 +50,19 @@ public CalendarRecyclerView(Context context, AttributeSet attrs) { public CalendarRecyclerView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - init(context); + init(context, attrs); } - private void init(Context context) { + private void init(Context context, AttributeSet attrs) { this.context = context; + + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomizableCalendar); + if (typedArray != null) { + monthResId = typedArray.getResourceId(R.styleable.CustomizableCalendar_month_layout, R.layout.calendar_view); + monthCellResId = typedArray.getResourceId(R.styleable.CustomizableCalendar_cell_layout, R.layout.calendar_cell); + typedArray.recycle(); + } + linearLayoutManager = new LinearLayoutManager(getContext()); linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); setLayoutManager(linearLayoutManager); @@ -82,6 +98,8 @@ public void injectPresenter(CustomizableCalendarPresenter presenter) { private void setupCalendarAdapter() { calendarViewAdapter = new CalendarViewAdapter(context); calendarViewAdapter.injectViewInteractor(viewInteractor); + calendarViewAdapter.setLayoutResId(monthResId); + calendarViewAdapter.setDayLayoutResId(monthCellResId); setAdapter(calendarViewAdapter); } diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/MonthGridView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/MonthGridView.java index dc0c50b..5b3d5da 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/MonthGridView.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/MonthGridView.java @@ -55,6 +55,7 @@ private void init(Context context, AttributeSet attrs) { TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomizableCalendar); if (typedArray != null) { layoutResId = typedArray.getResourceId(R.styleable.CustomizableCalendar_month_layout, R.layout.calendar_view); + dayLayoutResId = typedArray.getResourceId(R.styleable.CustomizableCalendar_cell_layout, R.layout.calendar_cell); typedArray.recycle(); } diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/WeekDaysView.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/WeekDaysView.java index 001749c..4694583 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/WeekDaysView.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/components/WeekDaysView.java @@ -28,7 +28,6 @@ public class WeekDaysView extends RecyclerView implements com.francesco.furlan.c WeekDaysViewAdapter weekDaysViewAdapter; private Context context; private @LayoutRes int layoutResId = -1; - private @LayoutRes int dayLayoutResId = -1; private ViewInteractor viewInteractor; private Integer firstDayOfWeek; private CustomizableCalendarPresenter presenter; @@ -51,7 +50,7 @@ private void init(Context context, AttributeSet attrs) { TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomizableCalendar); layoutResId = R.layout.week_day_view; if (typedArray != null) { - layoutResId = typedArray.getResourceId(R.styleable.CustomizableCalendar_weekDayLayout, R.layout.week_day_view); + layoutResId = typedArray.getResourceId(R.styleable.CustomizableCalendar_layout, R.layout.week_day_view); typedArray.recycle(); } } diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml index 08d708c..d2fdacd 100644 --- a/library/src/main/res/values/attrs.xml +++ b/library/src/main/res/values/attrs.xml @@ -4,6 +4,5 @@ - \ No newline at end of file From b38e0e9d62248f1b27f94849e8b58150c2a0c0fd Mon Sep 17 00:00:00 2001 From: Francesco Furlan Date: Wed, 5 Jul 2017 12:53:25 +0200 Subject: [PATCH 30/30] added getMonthGridView interaction for custom layouts --- .../furlan/customizablecalendar/CalendarViewInteractor.java | 5 +++++ .../library/adapter/CalendarViewAdapter.java | 4 +++- .../library/interactors/ViewInteractor.java | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/francesco/furlan/customizablecalendar/CalendarViewInteractor.java b/app/src/main/java/com/francesco/furlan/customizablecalendar/CalendarViewInteractor.java index 1e4cb4d..15fcd1f 100644 --- a/app/src/main/java/com/francesco/furlan/customizablecalendar/CalendarViewInteractor.java +++ b/app/src/main/java/com/francesco/furlan/customizablecalendar/CalendarViewInteractor.java @@ -98,6 +98,11 @@ public boolean hasImplementedMonthCellBinding() { return false; } + @Override + public View getMonthGridView(View rootView) { + return null; + } + void updateCalendar(Calendar calendar) { this.calendar = calendar; if (firstDaySelectedTxt != null && lastDaySelectedTxt != null) { diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/CalendarViewAdapter.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/CalendarViewAdapter.java index 441aeeb..a0408ff 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/CalendarViewAdapter.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/adapter/CalendarViewAdapter.java @@ -8,6 +8,7 @@ import android.view.ViewGroup; import android.widget.LinearLayout; +import com.francesco.furlan.customizablecalendar.library.R; import com.francesco.furlan.customizablecalendar.library.components.MonthGridView; import com.francesco.furlan.customizablecalendar.library.interactors.AUCalendar; import com.francesco.furlan.customizablecalendar.library.interactors.ViewInteractor; @@ -38,8 +39,9 @@ public int getItemCount() { @Override public CalendarViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { View rootView; - if (layoutResId != -1) { + if (layoutResId != -1 && layoutResId != R.layout.calendar_view) { rootView = LayoutInflater.from(context).inflate(layoutResId, null); + rootView = viewInteractor.getMonthGridView(rootView); } else { MonthGridView monthGridView = new MonthGridView(context); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); diff --git a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/ViewInteractor.java b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/ViewInteractor.java index 5bf16f7..c5085aa 100644 --- a/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/ViewInteractor.java +++ b/library/src/main/java/com/francesco/furlan/customizablecalendar/library/interactors/ViewInteractor.java @@ -40,4 +40,6 @@ public interface ViewInteractor { int setSelected(boolean multipleSelection, DateTime dateSelected); boolean hasImplementedMonthCellBinding(); + + View getMonthGridView(View rootView); }