From 86f8a1c34e1645df306c8ddc9da9b9da7c40fde5 Mon Sep 17 00:00:00 2001 From: Quentin Colle Date: Wed, 25 Jul 2018 18:03:06 -0400 Subject: [PATCH] Chore - Code Style (#825) --- build.gradle | 34 +- gradle.properties | 4 +- gradle/wrapper/gradle-wrapper.properties | 10 +- library/build.gradle | 72 +- .../AnimatorListener.java | 24 +- .../materialcalendarview/CalendarDay.java | 345 +- .../materialcalendarview/CalendarMode.java | 30 +- .../materialcalendarview/CalendarPager.java | 89 +- .../CalendarPagerAdapter.java | 607 ++- .../CalendarPagerView.java | 645 ++- .../materialcalendarview/DayView.java | 462 +- .../DayViewDecorator.java | 27 +- .../materialcalendarview/DayViewFacade.java | 229 +- .../materialcalendarview/DecoratorResult.java | 12 +- .../materialcalendarview/DirectionButton.java | 62 +- .../MaterialCalendarView.java | 3898 +++++++++-------- .../MonthPagerAdapter.java | 4 - .../materialcalendarview/MonthView.java | 59 +- .../OnDateLongClickListener.java | 16 +- .../OnDateSelectedListener.java | 21 +- .../OnMonthChangedListener.java | 14 +- .../OnRangeSelectedListener.java | 17 +- .../materialcalendarview/TitleChanger.java | 205 +- .../materialcalendarview/WeekDayView.java | 40 +- .../WeekPagerAdapter.java | 1 - .../materialcalendarview/WeekView.java | 45 +- .../format/ArrayWeekDayFormatter.java | 36 +- .../format/DateFormatDayFormatter.java | 53 +- .../format/DateFormatTitleFormatter.java | 43 +- .../format/DayFormatter.java | 32 +- .../format/MonthArrayTitleFormatter.java | 49 +- .../format/TitleFormatter.java | 18 +- .../format/WeekDayFormatter.java | 22 +- .../materialcalendarview/spans/DotSpan.java | 120 +- .../src/main/res/color/mcv_text_date_dark.xml | 11 +- .../main/res/color/mcv_text_date_light.xml | 11 +- library/src/main/res/values/attrs.xml | 112 +- library/src/main/res/values/ids.xml | 2 +- library/src/main/res/values/strings.xml | 6 +- library/src/main/res/values/styles.xml | 26 +- .../MonthlyRangeIndexTest.java | 10 +- .../WeeklyRangeIndexTest.java | 13 +- .../format/CalendarWeekDayFormatterTest.java | 76 +- sample/build.gradle | 50 +- sample/src/main/AndroidManifest.xml | 498 +-- .../sample/BasicActivity.java | 90 +- .../sample/BasicActivityDecorated.java | 128 +- .../sample/CustomTileDimensions.java | 44 +- .../sample/CustomizeCodeActivity.java | 78 +- .../sample/CustomizeXmlActivity.java | 21 +- .../sample/DialogsActivity.java | 104 +- .../sample/DisableDaysActivity.java | 154 +- .../sample/DynamicSettersActivity.java | 610 +-- .../sample/MainActivity.java | 125 +- .../sample/MultipleSizeActivity.java | 10 +- .../sample/MultipleViewActivity.java | 94 +- .../sample/OldCalendarViewActivity.java | 43 +- .../sample/SelectionModesActivity.java | 10 +- .../SwappableBasicActivityDecorated.java | 88 +- .../sample/decorators/EventDecorator.java | 29 +- .../HighlightWeekendsDecorator.java | 26 +- .../decorators/MySelectorDecorator.java | 25 +- .../sample/decorators/OneDayDecorator.java | 48 +- .../sample/decorators/RangeDayDecorator.java | 6 - sample/src/main/res/drawable/my_selector.xml | 8 +- .../res/drawable/today_circle_background.xml | 5 +- sample/src/main/res/layout/activity_basic.xml | 26 +- .../main/res/layout/activity_basic_modes.xml | 48 +- .../main/res/layout/activity_custom_tile.xml | 106 +- .../res/layout/activity_customization.xml | 38 +- .../src/main/res/layout/activity_dialogs.xml | 24 +- .../res/layout/activity_dynamic_setters.xml | 508 +-- .../res/layout/activity_multiple_size.xml | 129 +- .../res/layout/activity_old_calendarview.xml | 26 +- sample/src/main/res/layout/dialog_basic.xml | 26 +- sample/src/main/res/menu/menu_main.xml | 12 +- sample/src/main/res/values/colors.xml | 4 +- sample/src/main/res/values/dimens.xml | 12 +- sample/src/main/res/values/strings.xml | 90 +- sample/src/main/res/values/styles.xml | 22 +- 80 files changed, 5483 insertions(+), 5494 deletions(-) diff --git a/build.gradle b/build.gradle index 0df6d80d..1a29a9cf 100644 --- a/build.gradle +++ b/build.gradle @@ -1,29 +1,29 @@ task wrapper(type: Wrapper) { - //if you change this version you will need to run the 'gradlew wrapper' command twice from the command line to auto update the gradle cache - gradleVersion = "4.7" + //if you change this version you will need to run the 'gradlew wrapper' command twice from the command line to auto update the gradle cache + gradleVersion = "4.7" } buildscript { - repositories { - google() - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:3.1.2' - classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' - } + repositories { + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.1.2' + classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' + } } allprojects { - repositories { - google() - jcenter() - // Here for convience when testing new releases - // maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } - } + repositories { + google() + jcenter() + // Here for convience when testing new releases + // maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } + } } task clean(type: Delete) { - delete rootProject.buildDir + delete rootProject.buildDir } apply from: rootProject.file('dependencies.gradle') diff --git a/gradle.properties b/gradle.properties index 19d5f9b4..32a792ac 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,5 +17,5 @@ # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true -VERSION_NAME = 1.5.0 -VERSION_CODE = 18 \ No newline at end of file +VERSION_NAME = 1.5.0 +VERSION_CODE = 18 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 16d28051..0b905100 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists +distributionBase = GRADLE_USER_HOME +distributionPath = wrapper/dists +distributionUrl = https\://services.gradle.org/distributions/gradle-4.7-bin.zip +zipStoreBase = GRADLE_USER_HOME +zipStorePath = wrapper/dists diff --git a/library/build.gradle b/library/build.gradle index 0dcd04fa..52ddc7af 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -3,55 +3,55 @@ apply plugin: 'maven' apply plugin: 'com.github.dcendents.android-maven' android { - compileSdkVersion rootProject.ext.compileSdkVersion + compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion + defaultConfig { + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion - versionCode Integer.parseInt(project.VERSION_CODE) - versionName project.VERSION_NAME - } + versionCode Integer.parseInt(project.VERSION_CODE) + versionName project.VERSION_NAME + } - lintOptions { - abortOnError false - } + lintOptions { + abortOnError false + } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } } dependencies { - implementation rootProject.ext.threeTenAbp - implementation rootProject.ext.supportV4 - implementation rootProject.ext.supportAppCompat - implementation rootProject.ext.supportAnnotations + implementation rootProject.ext.threeTenAbp + implementation rootProject.ext.supportV4 + implementation rootProject.ext.supportAppCompat + implementation rootProject.ext.supportAnnotations - rootProject.ext.testDep.each { testImplementation it } - rootProject.ext.androidTestDep.each { androidTestImplementation it } + rootProject.ext.testDep.each { testImplementation it } + rootProject.ext.androidTestDep.each { androidTestImplementation it } } tasks.withType(Javadoc) { - options.addStringOption('Xdoclint:none', '-quiet') - options.addStringOption('encoding', 'UTF-8') - options.addStringOption('charSet', 'UTF-8') + options.addStringOption('Xdoclint:none', '-quiet') + options.addStringOption('encoding', 'UTF-8') + options.addStringOption('charSet', 'UTF-8') } android.libraryVariants.all { variant -> - task("generate${variant.name.capitalize()}Javadoc", type: Javadoc) { - title "Material CalendarView ${version}" - description "Generates Javadoc for $variant.name." - source = variant.javaCompiler.source - doFirst { - classpath = files(variant.javaCompiler.classpath.files, project.android.getBootClasspath()) - } - exclude '**/BuildConfig.java' - exclude '**/R.java' - options { - links "http://docs.oracle.com/javase/7/docs/api/" - linksOffline "http://d.android.com/reference", "${android.sdkDirectory}/docs/reference" - } + task("generate${variant.name.capitalize()}Javadoc", type: Javadoc) { + title "Material CalendarView ${version}" + description "Generates Javadoc for $variant.name." + source = variant.javaCompiler.source + doFirst { + classpath = files(variant.javaCompiler.classpath.files, project.android.getBootClasspath()) + } + exclude '**/BuildConfig.java' + exclude '**/R.java' + options { + links "http://docs.oracle.com/javase/7/docs/api/" + linksOffline "http://d.android.com/reference", "${android.sdkDirectory}/docs/reference" } + } } \ No newline at end of file diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/AnimatorListener.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/AnimatorListener.java index d4a793be..cf9ee34d 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/AnimatorListener.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/AnimatorListener.java @@ -3,19 +3,19 @@ import android.animation.Animator; class AnimatorListener implements Animator.AnimatorListener { - @Override - public void onAnimationStart(Animator animator) { - } + @Override + public void onAnimationStart(Animator animator) { + } - @Override - public void onAnimationEnd(Animator animator) { - } + @Override + public void onAnimationEnd(Animator animator) { + } - @Override - public void onAnimationCancel(Animator animator) { - } + @Override + public void onAnimationCancel(Animator animator) { + } - @Override - public void onAnimationRepeat(Animator animator) { - } + @Override + public void onAnimationRepeat(Animator animator) { + } } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarDay.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarDay.java index 4c190dad..4a0b073d 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarDay.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarDay.java @@ -4,7 +4,6 @@ import android.os.Parcelable; import android.support.annotation.NonNull; import android.support.annotation.Nullable; - import org.threeten.bp.LocalDate; /** @@ -12,176 +11,176 @@ */ public final class CalendarDay implements Parcelable { - /** - * Everything is based on this variable for {@link CalendarDay}. - */ - @NonNull private final LocalDate date; - - /** - * @param year new instance's year - * @param month new instance's month as defined by {@linkplain java.util.Calendar} - * @param day new instance's day of month - */ - private CalendarDay(final int year, final int month, final int day) { - date = LocalDate.of(year, month, day); - } - - /** - * @param date {@link LocalDate} instance - */ - private CalendarDay(@NonNull final LocalDate date) { - this.date = date; - } - - /** - * Get a new instance set to today - * - * @return CalendarDay set to today's date - */ - @NonNull public static CalendarDay today() { - return from(LocalDate.now()); - } - - /** - * Get a new instance set to the specified day - * - * @param year new instance's year - * @param month new instance's month as defined by {@linkplain java.util.Calendar} - * @param day new instance's day of month - * @return CalendarDay set to the specified date - */ - @NonNull public static CalendarDay from(int year, int month, int day) { - return new CalendarDay(year, month, day); - } - - /** - * Get a new instance set to the specified day - * - * @param date {@linkplain LocalDate} to pull date information from. Passing null will return null - * @return CalendarDay set to the specified date - */ - public static CalendarDay from(@Nullable LocalDate date) { - if (date == null) { - return null; - } - return new CalendarDay(date); - } - - /** - * Get the year - * - * @return the year for this day - */ - public int getYear() { - return date.getYear(); - } - - /** - * Get the month, represented by values from {@linkplain LocalDate} - * - * @return the month of the year as defined by {@linkplain LocalDate} - */ - public int getMonth() { - return date.getMonthValue(); - } - - /** - * Get the day - * - * @return the day of the month for this day - */ - public int getDay() { - return date.getDayOfMonth(); - } - - /** - * Get this day as a {@linkplain LocalDate} - * - * @return a date with this days information - */ - @NonNull public LocalDate getDate() { - return date; - } - - /** - * Determine if this day is within a specified range - * - * @param minDate the earliest day, may be null - * @param maxDate the latest day, may be null - * @return true if the between (inclusive) the min and max dates. - */ - public boolean isInRange(@Nullable CalendarDay minDate, @Nullable CalendarDay maxDate) { - return !(minDate != null && minDate.isAfter(this)) && - !(maxDate != null && maxDate.isBefore(this)); - } - - /** - * Determine if this day is before the given instance - * - * @param other the other day to test - * @return true if this is before other, false if equal or after - */ - public boolean isBefore(@NonNull final CalendarDay other) { - return date.isBefore(other.getDate()); - } - - /** - * Determine if this day is after the given instance - * - * @param other the other day to test - * @return true if this is after other, false if equal or before - */ - public boolean isAfter(@NonNull final CalendarDay other) { - return date.isAfter(other.getDate()); - } - - @Override public boolean equals(Object o) { - return o instanceof CalendarDay && date.equals(((CalendarDay) o).getDate()); - } - - @Override - public int hashCode() { - return hashCode(date.getYear(), date.getMonthValue(), date.getDayOfMonth()); - } - - private static int hashCode(int year, int month, int day) { - //Should produce hashes like "20150401" - return (year * 10000) + (month * 100) + day; - } - - @Override - public String toString() { - return "CalendarDay{" + date.getYear() + "-" + date.getMonthValue() + "-" - + date.getDayOfMonth() + "}"; - } - - /* - * Parcelable Stuff - */ - - public CalendarDay(Parcel in) { - this(in.readInt(), in.readInt(), in.readInt()); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(date.getYear()); - dest.writeInt(date.getMonthValue()); - dest.writeInt(date.getDayOfMonth()); - } - - public static final Creator CREATOR = new Creator() { - public CalendarDay createFromParcel(Parcel in) { - return new CalendarDay(in); - } - - public CalendarDay[] newArray(int size) { - return new CalendarDay[size]; - } - }; + /** + * Everything is based on this variable for {@link CalendarDay}. + */ + @NonNull private final LocalDate date; + + /** + * @param year new instance's year + * @param month new instance's month as defined by {@linkplain java.util.Calendar} + * @param day new instance's day of month + */ + private CalendarDay(final int year, final int month, final int day) { + date = LocalDate.of(year, month, day); + } + + /** + * @param date {@link LocalDate} instance + */ + private CalendarDay(@NonNull final LocalDate date) { + this.date = date; + } + + /** + * Get a new instance set to today + * + * @return CalendarDay set to today's date + */ + @NonNull public static CalendarDay today() { + return from(LocalDate.now()); + } + + /** + * Get a new instance set to the specified day + * + * @param year new instance's year + * @param month new instance's month as defined by {@linkplain java.util.Calendar} + * @param day new instance's day of month + * @return CalendarDay set to the specified date + */ + @NonNull public static CalendarDay from(int year, int month, int day) { + return new CalendarDay(year, month, day); + } + + /** + * Get a new instance set to the specified day + * + * @param date {@linkplain LocalDate} to pull date information from. Passing null will return null + * @return CalendarDay set to the specified date + */ + public static CalendarDay from(@Nullable LocalDate date) { + if (date == null) { + return null; + } + return new CalendarDay(date); + } + + /** + * Get the year + * + * @return the year for this day + */ + public int getYear() { + return date.getYear(); + } + + /** + * Get the month, represented by values from {@linkplain LocalDate} + * + * @return the month of the year as defined by {@linkplain LocalDate} + */ + public int getMonth() { + return date.getMonthValue(); + } + + /** + * Get the day + * + * @return the day of the month for this day + */ + public int getDay() { + return date.getDayOfMonth(); + } + + /** + * Get this day as a {@linkplain LocalDate} + * + * @return a date with this days information + */ + @NonNull public LocalDate getDate() { + return date; + } + + /** + * Determine if this day is within a specified range + * + * @param minDate the earliest day, may be null + * @param maxDate the latest day, may be null + * @return true if the between (inclusive) the min and max dates. + */ + public boolean isInRange(@Nullable CalendarDay minDate, @Nullable CalendarDay maxDate) { + return !(minDate != null && minDate.isAfter(this)) && + !(maxDate != null && maxDate.isBefore(this)); + } + + /** + * Determine if this day is before the given instance + * + * @param other the other day to test + * @return true if this is before other, false if equal or after + */ + public boolean isBefore(@NonNull final CalendarDay other) { + return date.isBefore(other.getDate()); + } + + /** + * Determine if this day is after the given instance + * + * @param other the other day to test + * @return true if this is after other, false if equal or before + */ + public boolean isAfter(@NonNull final CalendarDay other) { + return date.isAfter(other.getDate()); + } + + @Override public boolean equals(Object o) { + return o instanceof CalendarDay && date.equals(((CalendarDay) o).getDate()); + } + + @Override + public int hashCode() { + return hashCode(date.getYear(), date.getMonthValue(), date.getDayOfMonth()); + } + + private static int hashCode(int year, int month, int day) { + //Should produce hashes like "20150401" + return (year * 10000) + (month * 100) + day; + } + + @Override + public String toString() { + return "CalendarDay{" + date.getYear() + "-" + date.getMonthValue() + "-" + + date.getDayOfMonth() + "}"; + } + + /* + * Parcelable Stuff + */ + + public CalendarDay(Parcel in) { + this(in.readInt(), in.readInt(), in.readInt()); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(date.getYear()); + dest.writeInt(date.getMonthValue()); + dest.writeInt(date.getDayOfMonth()); + } + + public static final Creator CREATOR = new Creator() { + public CalendarDay createFromParcel(Parcel in) { + return new CalendarDay(in); + } + + public CalendarDay[] newArray(int size) { + return new CalendarDay[size]; + } + }; } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarMode.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarMode.java index fa53c8ca..3c704ad8 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarMode.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarMode.java @@ -5,21 +5,21 @@ */ public enum CalendarMode { - /** - * Month Mode to display an entire month per page. - */ - MONTHS(6), - /** - * Week mode that shows the calendar week by week. - */ - WEEKS(1); + /** + * Month Mode to display an entire month per page. + */ + MONTHS(6), + /** + * Week mode that shows the calendar week by week. + */ + WEEKS(1); - /** - * Number of visible weeks per calendar mode. - */ - final int visibleWeeksCount; + /** + * Number of visible weeks per calendar mode. + */ + final int visibleWeeksCount; - CalendarMode(int visibleWeeksCount) { - this.visibleWeeksCount = visibleWeeksCount; - } + CalendarMode(int visibleWeeksCount) { + this.visibleWeeksCount = visibleWeeksCount; + } } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarPager.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarPager.java index ef60df46..6f9072ad 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarPager.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarPager.java @@ -9,54 +9,53 @@ */ class CalendarPager extends ViewPager { - private boolean pagingEnabled = true; - - public CalendarPager(Context context) { - super(context); - } - + private boolean pagingEnabled = true; + + public CalendarPager(Context context) { + super(context); + } + + /** + * enable disable viewpager scroll + * + * @param pagingEnabled false to disable paging, true for paging (default) + */ + public void setPagingEnabled(boolean pagingEnabled) { + this.pagingEnabled = pagingEnabled; + } + + /** + * @return is this viewpager allowed to page + */ + public boolean isPagingEnabled() { + return pagingEnabled; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + return pagingEnabled && super.onInterceptTouchEvent(ev); + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + return pagingEnabled && super.onTouchEvent(ev); + } + + @Override + public boolean canScrollVertically(int direction) { /** - * enable disable viewpager scroll - * - * @param pagingEnabled false to disable paging, true for paging (default) + * disables scrolling vertically when paging disabled, fixes scrolling + * for nested {@link android.support.v4.view.ViewPager} */ - public void setPagingEnabled(boolean pagingEnabled) { - this.pagingEnabled = pagingEnabled; - } + return pagingEnabled && super.canScrollVertically(direction); + } + @Override + public boolean canScrollHorizontally(int direction) { /** - * @return is this viewpager allowed to page + * disables scrolling horizontally when paging disabled, fixes scrolling + * for nested {@link android.support.v4.view.ViewPager} */ - public boolean isPagingEnabled() { - return pagingEnabled; - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - return pagingEnabled && super.onInterceptTouchEvent(ev); - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - return pagingEnabled && super.onTouchEvent(ev); - } - - @Override - public boolean canScrollVertically(int direction) { - /** - * disables scrolling vertically when paging disabled, fixes scrolling - * for nested {@link android.support.v4.view.ViewPager} - */ - return pagingEnabled && super.canScrollVertically(direction); - } - - @Override - public boolean canScrollHorizontally(int direction) { - /** - * disables scrolling horizontally when paging disabled, fixes scrolling - * for nested {@link android.support.v4.view.ViewPager} - */ - return pagingEnabled && super.canScrollHorizontally(direction); - } - + return pagingEnabled && super.canScrollHorizontally(direction); + } } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarPagerAdapter.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarPagerAdapter.java index 1456e3f4..d4c68eae 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarPagerAdapter.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarPagerAdapter.java @@ -5,12 +5,10 @@ import android.support.v4.view.PagerAdapter; import android.view.View; import android.view.ViewGroup; - import com.prolificinteractive.materialcalendarview.MaterialCalendarView.ShowOtherDates; import com.prolificinteractive.materialcalendarview.format.DayFormatter; import com.prolificinteractive.materialcalendarview.format.TitleFormatter; import com.prolificinteractive.materialcalendarview.format.WeekDayFormatter; - import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; @@ -22,358 +20,359 @@ */ abstract class CalendarPagerAdapter extends PagerAdapter { - private final ArrayDeque currentViews; - - protected final MaterialCalendarView mcv; - private final CalendarDay today; - - @NonNull private TitleFormatter titleFormatter = TitleFormatter.DEFAULT; - private Integer color = null; - private Integer dateTextAppearance = null; - private Integer weekDayTextAppearance = null; - @ShowOtherDates - private int showOtherDates = MaterialCalendarView.SHOW_DEFAULTS; - private CalendarDay minDate = null; - private CalendarDay maxDate = null; - private DateRangeIndex rangeIndex; - private List selectedDates = new ArrayList<>(); - private WeekDayFormatter weekDayFormatter = WeekDayFormatter.DEFAULT; - private DayFormatter dayFormatter = DayFormatter.DEFAULT; - private DayFormatter dayFormatterContentDescription = dayFormatter; - private List decorators = new ArrayList<>(); - private List decoratorResults = null; - private boolean selectionEnabled = true; - boolean showWeekDays; - - CalendarPagerAdapter(MaterialCalendarView mcv) { - this.mcv = mcv; - this.today = CalendarDay.today(); - currentViews = new ArrayDeque<>(); - currentViews.iterator(); - setRangeDates(null, null); - } + private final ArrayDeque currentViews; + + protected final MaterialCalendarView mcv; + private final CalendarDay today; + + @NonNull private TitleFormatter titleFormatter = TitleFormatter.DEFAULT; + private Integer color = null; + private Integer dateTextAppearance = null; + private Integer weekDayTextAppearance = null; + @ShowOtherDates + private int showOtherDates = MaterialCalendarView.SHOW_DEFAULTS; + private CalendarDay minDate = null; + private CalendarDay maxDate = null; + private DateRangeIndex rangeIndex; + private List selectedDates = new ArrayList<>(); + private WeekDayFormatter weekDayFormatter = WeekDayFormatter.DEFAULT; + private DayFormatter dayFormatter = DayFormatter.DEFAULT; + private DayFormatter dayFormatterContentDescription = dayFormatter; + private List decorators = new ArrayList<>(); + private List decoratorResults = null; + private boolean selectionEnabled = true; + boolean showWeekDays; + + CalendarPagerAdapter(MaterialCalendarView mcv) { + this.mcv = mcv; + this.today = CalendarDay.today(); + currentViews = new ArrayDeque<>(); + currentViews.iterator(); + setRangeDates(null, null); + } + + public void setDecorators(List decorators) { + this.decorators = decorators; + invalidateDecorators(); + } + + public void invalidateDecorators() { + decoratorResults = new ArrayList<>(); + for (DayViewDecorator decorator : decorators) { + DayViewFacade facade = new DayViewFacade(); + decorator.decorate(facade); + if (facade.isDecorated()) { + decoratorResults.add(new DecoratorResult(decorator, facade)); + } + } + for (V pagerView : currentViews) { + pagerView.setDayViewDecorators(decoratorResults); + } + } + + @Override + public int getCount() { + return rangeIndex.getCount(); + } + + @Override + public CharSequence getPageTitle(int position) { + return titleFormatter.format(getItem(position)); + } + + public CalendarPagerAdapter migrateStateAndReturn(CalendarPagerAdapter newAdapter) { + newAdapter.titleFormatter = titleFormatter; + newAdapter.color = color; + newAdapter.dateTextAppearance = dateTextAppearance; + newAdapter.weekDayTextAppearance = weekDayTextAppearance; + newAdapter.showOtherDates = showOtherDates; + newAdapter.minDate = minDate; + newAdapter.maxDate = maxDate; + newAdapter.selectedDates = selectedDates; + newAdapter.weekDayFormatter = weekDayFormatter; + newAdapter.dayFormatter = dayFormatter; + newAdapter.dayFormatterContentDescription = dayFormatterContentDescription; + newAdapter.decorators = decorators; + newAdapter.decoratorResults = decoratorResults; + newAdapter.selectionEnabled = selectionEnabled; + return newAdapter; + } + + public int getIndexForDay(CalendarDay day) { + if (day == null) { + return getCount() / 2; + } + if (minDate != null && day.isBefore(minDate)) { + return 0; + } + if (maxDate != null && day.isAfter(maxDate)) { + return getCount() - 1; + } + return rangeIndex.indexOf(day); + } + + protected abstract V createView(int position); + + protected abstract int indexOf(V view); + + protected abstract boolean isInstanceOfView(Object object); + + protected abstract DateRangeIndex createRangeIndex(CalendarDay min, CalendarDay max); + + @Override + public int getItemPosition(@NonNull Object object) { + if (!(isInstanceOfView(object))) { + return POSITION_NONE; + } + CalendarPagerView pagerView = (CalendarPagerView) object; + CalendarDay firstViewDay = pagerView.getFirstViewDay(); + if (firstViewDay == null) { + return POSITION_NONE; + } + int index = indexOf((V) object); + if (index < 0) { + return POSITION_NONE; + } + return index; + } + + @NonNull + @Override + public Object instantiateItem(@NonNull ViewGroup container, int position) { + V pagerView = createView(position); + pagerView.setContentDescription(mcv.getCalendarContentDescription()); + pagerView.setAlpha(0); + pagerView.setSelectionEnabled(selectionEnabled); + + pagerView.setWeekDayFormatter(weekDayFormatter); + pagerView.setDayFormatter(dayFormatter); + pagerView.setDayFormatterContentDescription(dayFormatterContentDescription); + if (color != null) { + pagerView.setSelectionColor(color); + } + if (dateTextAppearance != null) { + pagerView.setDateTextAppearance(dateTextAppearance); + } + if (weekDayTextAppearance != null) { + pagerView.setWeekDayTextAppearance(weekDayTextAppearance); + } + pagerView.setShowOtherDates(showOtherDates); + pagerView.setMinimumDate(minDate); + pagerView.setMaximumDate(maxDate); + pagerView.setSelectedDates(selectedDates); + + container.addView(pagerView); + currentViews.add(pagerView); - public void setDecorators(List decorators) { - this.decorators = decorators; - invalidateDecorators(); - } + pagerView.setDayViewDecorators(decoratorResults); + + return pagerView; + } + + public void setShowWeekDays(boolean showWeekDays) { + this.showWeekDays = showWeekDays; + } - public void invalidateDecorators() { - decoratorResults = new ArrayList<>(); - for (DayViewDecorator decorator : decorators) { - DayViewFacade facade = new DayViewFacade(); - decorator.decorate(facade); - if (facade.isDecorated()) { - decoratorResults.add(new DecoratorResult(decorator, facade)); - } - } - for (V pagerView : currentViews) { - pagerView.setDayViewDecorators(decoratorResults); - } - } + public boolean isShowWeekDays() { + return showWeekDays; + } - @Override - public int getCount() { - return rangeIndex.getCount(); + public void setSelectionEnabled(boolean enabled) { + selectionEnabled = enabled; + for (V pagerView : currentViews) { + pagerView.setSelectionEnabled(selectionEnabled); } + } - @Override - public CharSequence getPageTitle(int position) { - return titleFormatter.format(getItem(position)); - } + @Override + public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { + V pagerView = (V) object; + currentViews.remove(pagerView); + container.removeView(pagerView); + } - public CalendarPagerAdapter migrateStateAndReturn(CalendarPagerAdapter newAdapter) { - newAdapter.titleFormatter = titleFormatter; - newAdapter.color = color; - newAdapter.dateTextAppearance = dateTextAppearance; - newAdapter.weekDayTextAppearance = weekDayTextAppearance; - newAdapter.showOtherDates = showOtherDates; - newAdapter.minDate = minDate; - newAdapter.maxDate = maxDate; - newAdapter.selectedDates = selectedDates; - newAdapter.weekDayFormatter = weekDayFormatter; - newAdapter.dayFormatter = dayFormatter; - newAdapter.dayFormatterContentDescription = dayFormatterContentDescription; - newAdapter.decorators = decorators; - newAdapter.decoratorResults = decoratorResults; - newAdapter.selectionEnabled = selectionEnabled; - return newAdapter; - } + @Override + public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { + return view == object; + } - public int getIndexForDay(CalendarDay day) { - if (day == null) { - return getCount() / 2; - } - if (minDate != null && day.isBefore(minDate)) { - return 0; - } - if (maxDate != null && day.isAfter(maxDate)) { - return getCount() - 1; - } - return rangeIndex.indexOf(day); - } + public void setTitleFormatter(@Nullable TitleFormatter titleFormatter) { + this.titleFormatter = titleFormatter == null ? TitleFormatter.DEFAULT : titleFormatter; + } - protected abstract V createView(int position); - - protected abstract int indexOf(V view); - - protected abstract boolean isInstanceOfView(Object object); - - protected abstract DateRangeIndex createRangeIndex(CalendarDay min, CalendarDay max); - - @Override - public int getItemPosition(@NonNull Object object) { - if (!(isInstanceOfView(object))) { - return POSITION_NONE; - } - CalendarPagerView pagerView = (CalendarPagerView) object; - CalendarDay firstViewDay = pagerView.getFirstViewDay(); - if (firstViewDay == null) { - return POSITION_NONE; - } - int index = indexOf((V) object); - if (index < 0) { - return POSITION_NONE; - } - return index; + public void setSelectionColor(int color) { + this.color = color; + for (V pagerView : currentViews) { + pagerView.setSelectionColor(color); } + } - @NonNull - @Override - public Object instantiateItem(@NonNull ViewGroup container, int position) { - V pagerView = createView(position); - pagerView.setContentDescription(mcv.getCalendarContentDescription()); - pagerView.setAlpha(0); - pagerView.setSelectionEnabled(selectionEnabled); - - pagerView.setWeekDayFormatter(weekDayFormatter); - pagerView.setDayFormatter(dayFormatter); - pagerView.setDayFormatterContentDescription(dayFormatterContentDescription); - if (color != null) { - pagerView.setSelectionColor(color); - } - if (dateTextAppearance != null) { - pagerView.setDateTextAppearance(dateTextAppearance); - } - if (weekDayTextAppearance != null) { - pagerView.setWeekDayTextAppearance(weekDayTextAppearance); - } - pagerView.setShowOtherDates(showOtherDates); - pagerView.setMinimumDate(minDate); - pagerView.setMaximumDate(maxDate); - pagerView.setSelectedDates(selectedDates); - - container.addView(pagerView); - currentViews.add(pagerView); - - pagerView.setDayViewDecorators(decoratorResults); - - return pagerView; + public void setDateTextAppearance(int taId) { + if (taId == 0) { + return; } - - public void setShowWeekDays(boolean showWeekDays) { - this.showWeekDays = showWeekDays; - } - - public boolean isShowWeekDays() { - return showWeekDays; - } - - public void setSelectionEnabled(boolean enabled) { - selectionEnabled = enabled; - for (V pagerView : currentViews) { - pagerView.setSelectionEnabled(selectionEnabled); - } - } - - @Override - public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { - V pagerView = (V) object; - currentViews.remove(pagerView); - container.removeView(pagerView); + this.dateTextAppearance = taId; + for (V pagerView : currentViews) { + pagerView.setDateTextAppearance(taId); } + } - @Override - public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { - return view == object; + public void setShowOtherDates(@ShowOtherDates int showFlags) { + this.showOtherDates = showFlags; + for (V pagerView : currentViews) { + pagerView.setShowOtherDates(showFlags); } + } - public void setTitleFormatter(@Nullable TitleFormatter titleFormatter) { - this.titleFormatter = titleFormatter == null ? TitleFormatter.DEFAULT : titleFormatter; + public void setWeekDayFormatter(WeekDayFormatter formatter) { + this.weekDayFormatter = formatter; + for (V pagerView : currentViews) { + pagerView.setWeekDayFormatter(formatter); } + } - public void setSelectionColor(int color) { - this.color = color; - for (V pagerView : currentViews) { - pagerView.setSelectionColor(color); - } + public void setDayFormatter(DayFormatter formatter) { + dayFormatterContentDescription = dayFormatterContentDescription == dayFormatter ? + formatter : dayFormatterContentDescription; + this.dayFormatter = formatter; + for (V pagerView : currentViews) { + pagerView.setDayFormatter(formatter); } + } - public void setDateTextAppearance(int taId) { - if (taId == 0) { - return; - } - this.dateTextAppearance = taId; - for (V pagerView : currentViews) { - pagerView.setDateTextAppearance(taId); - } + public void setDayFormatterContentDescription(DayFormatter formatter) { + dayFormatterContentDescription = formatter; + for (V pagerView : currentViews) { + pagerView.setDayFormatterContentDescription(formatter); } + } - public void setShowOtherDates(@ShowOtherDates int showFlags) { - this.showOtherDates = showFlags; - for (V pagerView : currentViews) { - pagerView.setShowOtherDates(showFlags); - } - } + @ShowOtherDates + public int getShowOtherDates() { + return showOtherDates; + } - public void setWeekDayFormatter(WeekDayFormatter formatter) { - this.weekDayFormatter = formatter; - for (V pagerView : currentViews) { - pagerView.setWeekDayFormatter(formatter); - } + public void setWeekDayTextAppearance(int taId) { + if (taId == 0) { + return; } - - public void setDayFormatter(DayFormatter formatter) { - dayFormatterContentDescription = dayFormatterContentDescription == dayFormatter ? - formatter : dayFormatterContentDescription; - this.dayFormatter = formatter; - for (V pagerView : currentViews) { - pagerView.setDayFormatter(formatter); - } + this.weekDayTextAppearance = taId; + for (V pagerView : currentViews) { + pagerView.setWeekDayTextAppearance(taId); } + } - public void setDayFormatterContentDescription(DayFormatter formatter) { - dayFormatterContentDescription = formatter; - for (V pagerView : currentViews) { - pagerView.setDayFormatterContentDescription(formatter); - } + public void setRangeDates(CalendarDay min, CalendarDay max) { + this.minDate = min; + this.maxDate = max; + for (V pagerView : currentViews) { + pagerView.setMinimumDate(min); + pagerView.setMaximumDate(max); } - @ShowOtherDates - public int getShowOtherDates() { - return showOtherDates; + if (min == null) { + min = CalendarDay.from(today.getYear() - 200, today.getMonth(), today.getDay()); } - public void setWeekDayTextAppearance(int taId) { - if (taId == 0) { - return; - } - this.weekDayTextAppearance = taId; - for (V pagerView : currentViews) { - pagerView.setWeekDayTextAppearance(taId); - } + if (max == null) { + max = CalendarDay.from(today.getYear() + 200, today.getMonth(), today.getDay()); } - public void setRangeDates(CalendarDay min, CalendarDay max) { - this.minDate = min; - this.maxDate = max; - for (V pagerView : currentViews) { - pagerView.setMinimumDate(min); - pagerView.setMaximumDate(max); - } + rangeIndex = createRangeIndex(min, max); - if (min == null) { - min = CalendarDay.from(today.getYear() - 200, today.getMonth(), today.getDay()); - } + notifyDataSetChanged(); + invalidateSelectedDates(); + } - if (max == null) { - max = CalendarDay.from(today.getYear() + 200, today.getMonth(), today.getDay()); - } + public DateRangeIndex getRangeIndex() { + return rangeIndex; + } - rangeIndex = createRangeIndex(min, max); + public void clearSelections() { + selectedDates.clear(); + invalidateSelectedDates(); + } - notifyDataSetChanged(); + /** + * Select or un-select a day. + * + * @param day Day to select or un-select + * @param selected Whether to select or un-select the day from the list. + * @see CalendarPagerAdapter#selectRange(CalendarDay, CalendarDay) + */ + public void setDateSelected(CalendarDay day, boolean selected) { + if (selected) { + if (!selectedDates.contains(day)) { + selectedDates.add(day); invalidateSelectedDates(); - } - - public DateRangeIndex getRangeIndex() { - return rangeIndex; - } - - public void clearSelections() { - selectedDates.clear(); + } + } else { + if (selectedDates.contains(day)) { + selectedDates.remove(day); invalidateSelectedDates(); + } } + } - /** - * Select or un-select a day. - * - * @param day Day to select or un-select - * @param selected Whether to select or un-select the day from the list. - * @see CalendarPagerAdapter#selectRange(CalendarDay, CalendarDay) - */ - public void setDateSelected(CalendarDay day, boolean selected) { - if (selected) { - if (!selectedDates.contains(day)) { - selectedDates.add(day); - invalidateSelectedDates(); - } - } else { - if (selectedDates.contains(day)) { - selectedDates.remove(day); - invalidateSelectedDates(); - } - } - } - - /** - * Clear the previous selection, select the range of days from first to last, and finally - * invalidate. First day should be before last day, otherwise the selection won't happen. - * - * @param first The first day of the range. - * @param last The last day in the range. - * @see CalendarPagerAdapter#setDateSelected(CalendarDay, boolean) - */ - public void selectRange(final CalendarDay first, final CalendarDay last) { - selectedDates.clear(); + /** + * Clear the previous selection, select the range of days from first to last, and finally + * invalidate. First day should be before last day, otherwise the selection won't happen. + * + * @param first The first day of the range. + * @param last The last day in the range. + * @see CalendarPagerAdapter#setDateSelected(CalendarDay, boolean) + */ + public void selectRange(final CalendarDay first, final CalendarDay last) { + selectedDates.clear(); - // Copy to start from the first day and increment - LocalDate temp = LocalDate.of(first.getYear(), first.getMonth(), first.getDay()); + // Copy to start from the first day and increment + LocalDate temp = LocalDate.of(first.getYear(), first.getMonth(), first.getDay()); - // for comparison - final LocalDate end = last.getDate(); + // for comparison + final LocalDate end = last.getDate(); - while (temp.isBefore(end) || temp.equals(end)) { - selectedDates.add(CalendarDay.from(temp)); - temp = temp.plusDays(1); - } - - invalidateSelectedDates(); + while( temp.isBefore(end) || temp.equals(end) ) { + selectedDates.add(CalendarDay.from(temp)); + temp = temp.plusDays(1); } - private void invalidateSelectedDates() { - validateSelectedDates(); - for (V pagerView : currentViews) { - pagerView.setSelectedDates(selectedDates); - } + invalidateSelectedDates(); + } + + private void invalidateSelectedDates() { + validateSelectedDates(); + for (V pagerView : currentViews) { + pagerView.setSelectedDates(selectedDates); } + } - private void validateSelectedDates() { - for (int i = 0; i < selectedDates.size(); i++) { - CalendarDay date = selectedDates.get(i); + private void validateSelectedDates() { + for (int i = 0; i < selectedDates.size(); i++) { + CalendarDay date = selectedDates.get(i); - if ((minDate != null && minDate.isAfter(date)) || (maxDate != null && maxDate.isBefore(date))) { - selectedDates.remove(i); - mcv.onDateUnselected(date); - i -= 1; - } - } + if ((minDate != null && minDate.isAfter(date)) || (maxDate != null + && maxDate.isBefore(date))) { + selectedDates.remove(i); + mcv.onDateUnselected(date); + i -= 1; + } } + } - public CalendarDay getItem(int position) { - return rangeIndex.getItem(position); - } + public CalendarDay getItem(int position) { + return rangeIndex.getItem(position); + } - @NonNull - public List getSelectedDates() { - return Collections.unmodifiableList(selectedDates); - } + @NonNull + public List getSelectedDates() { + return Collections.unmodifiableList(selectedDates); + } - protected int getDateTextAppearance() { - return dateTextAppearance == null ? 0 : dateTextAppearance; - } + protected int getDateTextAppearance() { + return dateTextAppearance == null ? 0 : dateTextAppearance; + } - protected int getWeekDayTextAppearance() { - return weekDayTextAppearance == null ? 0 : weekDayTextAppearance; - } + protected int getWeekDayTextAppearance() { + return weekDayTextAppearance == null ? 0 : weekDayTextAppearance; + } } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarPagerView.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarPagerView.java index 0cfeb1b7..5be5b005 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarPagerView.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarPagerView.java @@ -7,11 +7,9 @@ import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; - import com.prolificinteractive.materialcalendarview.MaterialCalendarView.ShowOtherDates; import com.prolificinteractive.materialcalendarview.format.DayFormatter; import com.prolificinteractive.materialcalendarview.format.WeekDayFormatter; - import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -23,356 +21,353 @@ import static com.prolificinteractive.materialcalendarview.MaterialCalendarView.SHOW_DEFAULTS; import static com.prolificinteractive.materialcalendarview.MaterialCalendarView.showOtherMonths; -abstract class CalendarPagerView extends ViewGroup implements View.OnClickListener, View.OnLongClickListener { - - protected static final int DEFAULT_DAYS_IN_WEEK = 7; - protected static final int DEFAULT_MAX_WEEKS = 6; - protected static final int DAY_NAMES_ROW = 1; - - private final ArrayList weekDayViews = new ArrayList<>(); - private final ArrayList decoratorResults = new ArrayList<>(); - private final DayOfWeek firstDayOfWeek; - @ShowOtherDates protected int showOtherDates = SHOW_DEFAULTS; - private MaterialCalendarView mcv; - private CalendarDay firstViewDay; - private CalendarDay minDate = null; - private CalendarDay maxDate = null; - protected boolean showWeekDays; - - private final Collection dayViews = new ArrayList<>(); - - public CalendarPagerView( - @NonNull MaterialCalendarView view, - CalendarDay firstViewDay, - DayOfWeek firstDayOfWeek, - boolean showWeekDays) { - super(view.getContext()); - - this.mcv = view; - this.firstViewDay = firstViewDay; - this.firstDayOfWeek = firstDayOfWeek; - this.showWeekDays = showWeekDays; - - setClipChildren(false); - setClipToPadding(false); - - if (LocalUtils.isRTL()) { - this.setRotationY(180); - } - - if (showWeekDays) { - buildWeekDays(resetAndGetWorkingCalendar()); - } - buildDayViews(dayViews, resetAndGetWorkingCalendar()); - } - - private void buildWeekDays(LocalDate calendar) { - LocalDate local = calendar; - for (int i = 0; i < DEFAULT_DAYS_IN_WEEK; i++) { - WeekDayView weekDayView = new WeekDayView(getContext(), local.getDayOfWeek()); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - weekDayView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); - } - weekDayViews.add(weekDayView); - addView(weekDayView); - local = local.plusDays(1); - } - } - - protected void addDayView(Collection dayViews, LocalDate temp) { - CalendarDay day = CalendarDay.from(temp); - DayView dayView = new DayView(getContext(), day); - dayView.setOnClickListener(this); - dayView.setOnLongClickListener(this); - dayViews.add(dayView); - addView(dayView, new LayoutParams()); - } - - protected LocalDate resetAndGetWorkingCalendar() { - final TemporalField firstDayOfWeek = WeekFields.of(this.firstDayOfWeek, 1).dayOfWeek(); - final LocalDate temp = getFirstViewDay().getDate().with(firstDayOfWeek, 1); - int dow = temp.getDayOfWeek().getValue(); - int delta = getFirstDayOfWeek().getValue() - dow; - //If the delta is positive, we want to remove a week - boolean removeRow = showOtherMonths(showOtherDates) ? delta >= 0 : delta > 0; - if (removeRow) { - delta -= DEFAULT_DAYS_IN_WEEK; - } - return temp.plusDays(delta); - } - - protected DayOfWeek getFirstDayOfWeek() { - return firstDayOfWeek; - } - - protected abstract void buildDayViews(Collection dayViews, LocalDate calendar); - - protected abstract boolean isDayEnabled(CalendarDay day); - - void setDayViewDecorators(List results) { - this.decoratorResults.clear(); - if (results != null) { - this.decoratorResults.addAll(results); - } - invalidateDecorators(); - } - - public void setWeekDayTextAppearance(int taId) { - for (WeekDayView weekDayView : weekDayViews) { - weekDayView.setTextAppearance(getContext(), taId); - } - } - - public void setDateTextAppearance(int taId) { - for (DayView dayView : dayViews) { - dayView.setTextAppearance(getContext(), taId); - } - } +abstract class CalendarPagerView extends ViewGroup + implements View.OnClickListener, View.OnLongClickListener { + + protected static final int DEFAULT_DAYS_IN_WEEK = 7; + protected static final int DEFAULT_MAX_WEEKS = 6; + protected static final int DAY_NAMES_ROW = 1; + + private final ArrayList weekDayViews = new ArrayList<>(); + private final ArrayList decoratorResults = new ArrayList<>(); + private final DayOfWeek firstDayOfWeek; + @ShowOtherDates protected int showOtherDates = SHOW_DEFAULTS; + private MaterialCalendarView mcv; + private CalendarDay firstViewDay; + private CalendarDay minDate = null; + private CalendarDay maxDate = null; + protected boolean showWeekDays; + + private final Collection dayViews = new ArrayList<>(); + + public CalendarPagerView( + @NonNull MaterialCalendarView view, + CalendarDay firstViewDay, + DayOfWeek firstDayOfWeek, + boolean showWeekDays) { + super(view.getContext()); - public void setShowOtherDates(@ShowOtherDates int showFlags) { - this.showOtherDates = showFlags; - updateUi(); - } + this.mcv = view; + this.firstViewDay = firstViewDay; + this.firstDayOfWeek = firstDayOfWeek; + this.showWeekDays = showWeekDays; - public void setSelectionEnabled(boolean selectionEnabled) { - for (DayView dayView : dayViews) { - dayView.setOnClickListener(selectionEnabled ? this : null); - dayView.setClickable(selectionEnabled); - } - } + setClipChildren(false); + setClipToPadding(false); - public void setSelectionColor(int color) { - for (DayView dayView : dayViews) { - dayView.setSelectionColor(color); - } + if (LocalUtils.isRTL()) { + this.setRotationY(180); } - public void setWeekDayFormatter(WeekDayFormatter formatter) { - for (WeekDayView dayView : weekDayViews) { - dayView.setWeekDayFormatter(formatter); - } + if (showWeekDays) { + buildWeekDays(resetAndGetWorkingCalendar()); } + buildDayViews(dayViews, resetAndGetWorkingCalendar()); + } - public void setDayFormatter(DayFormatter formatter) { - for (DayView dayView : dayViews) { - dayView.setDayFormatter(formatter); - } + private void buildWeekDays(LocalDate calendar) { + LocalDate local = calendar; + for (int i = 0; i < DEFAULT_DAYS_IN_WEEK; i++) { + WeekDayView weekDayView = new WeekDayView(getContext(), local.getDayOfWeek()); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + weekDayView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); + } + weekDayViews.add(weekDayView); + addView(weekDayView); + local = local.plusDays(1); } + } - public void setDayFormatterContentDescription(DayFormatter formatter) { - for (DayView dayView : dayViews) { - dayView.setDayFormatterContentDescription(formatter); - } - } + protected void addDayView(Collection dayViews, LocalDate temp) { + CalendarDay day = CalendarDay.from(temp); + DayView dayView = new DayView(getContext(), day); + dayView.setOnClickListener(this); + dayView.setOnLongClickListener(this); + dayViews.add(dayView); + addView(dayView, new LayoutParams()); + } - public void setMinimumDate(CalendarDay minDate) { - this.minDate = minDate; - updateUi(); + protected LocalDate resetAndGetWorkingCalendar() { + final TemporalField firstDayOfWeek = WeekFields.of(this.firstDayOfWeek, 1).dayOfWeek(); + final LocalDate temp = getFirstViewDay().getDate().with(firstDayOfWeek, 1); + int dow = temp.getDayOfWeek().getValue(); + int delta = getFirstDayOfWeek().getValue() - dow; + //If the delta is positive, we want to remove a week + boolean removeRow = showOtherMonths(showOtherDates) ? delta >= 0 : delta > 0; + if (removeRow) { + delta -= DEFAULT_DAYS_IN_WEEK; + } + return temp.plusDays(delta); + } + + protected DayOfWeek getFirstDayOfWeek() { + return firstDayOfWeek; + } + + protected abstract void buildDayViews(Collection dayViews, LocalDate calendar); + + protected abstract boolean isDayEnabled(CalendarDay day); + + void setDayViewDecorators(List results) { + this.decoratorResults.clear(); + if (results != null) { + this.decoratorResults.addAll(results); + } + invalidateDecorators(); + } + + public void setWeekDayTextAppearance(int taId) { + for (WeekDayView weekDayView : weekDayViews) { + weekDayView.setTextAppearance(getContext(), taId); + } + } + + public void setDateTextAppearance(int taId) { + for (DayView dayView : dayViews) { + dayView.setTextAppearance(getContext(), taId); + } + } + + public void setShowOtherDates(@ShowOtherDates int showFlags) { + this.showOtherDates = showFlags; + updateUi(); + } + + public void setSelectionEnabled(boolean selectionEnabled) { + for (DayView dayView : dayViews) { + dayView.setOnClickListener(selectionEnabled ? this : null); + dayView.setClickable(selectionEnabled); } + } - public void setMaximumDate(CalendarDay maxDate) { - this.maxDate = maxDate; - updateUi(); + public void setSelectionColor(int color) { + for (DayView dayView : dayViews) { + dayView.setSelectionColor(color); } + } - public void setSelectedDates(Collection dates) { - for (DayView dayView : dayViews) { - CalendarDay day = dayView.getDate(); - dayView.setChecked(dates != null && dates.contains(day)); - } - postInvalidate(); - } - - protected void updateUi() { - for (DayView dayView : dayViews) { - CalendarDay day = dayView.getDate(); - dayView.setupSelection(showOtherDates, day.isInRange(minDate, maxDate), isDayEnabled(day)); - } - postInvalidate(); + public void setWeekDayFormatter(WeekDayFormatter formatter) { + for (WeekDayView dayView : weekDayViews) { + dayView.setWeekDayFormatter(formatter); } + } - protected void invalidateDecorators() { - final DayViewFacade facadeAccumulator = new DayViewFacade(); - for (DayView dayView : dayViews) { - facadeAccumulator.reset(); - for (DecoratorResult result : decoratorResults) { - if (result.decorator.shouldDecorate(dayView.getDate())) { - result.result.applyTo(facadeAccumulator); - } - } - dayView.applyFacade(facadeAccumulator); - } - } - - @Override - public void onClick(final View v) { - if (v instanceof DayView) { - final DayView dayView = (DayView) v; - mcv.onDateClicked(dayView); - } - } - - @Override - public boolean onLongClick(final View v) { - if (v instanceof DayView) { - final DayView dayView = (DayView) v; - mcv.onDateLongClicked(dayView); - return true; - } - return false; + public void setDayFormatter(DayFormatter formatter) { + for (DayView dayView : dayViews) { + dayView.setDayFormatter(formatter); } + } - /* - * Custom ViewGroup Code - */ + public void setDayFormatterContentDescription(DayFormatter formatter) { + for (DayView dayView : dayViews) { + dayView.setDayFormatterContentDescription(formatter); + } + } + + public void setMinimumDate(CalendarDay minDate) { + this.minDate = minDate; + updateUi(); + } + + public void setMaximumDate(CalendarDay maxDate) { + this.maxDate = maxDate; + updateUi(); + } - /** - * {@inheritDoc} - */ - @Override - protected LayoutParams generateDefaultLayoutParams() { - return new LayoutParams(); + public void setSelectedDates(Collection dates) { + for (DayView dayView : dayViews) { + CalendarDay day = dayView.getDate(); + dayView.setChecked(dates != null && dates.contains(day)); } + postInvalidate(); + } - /** - * {@inheritDoc} - */ - @Override - protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { - final int specWidthSize = MeasureSpec.getSize(widthMeasureSpec); - final int specWidthMode = MeasureSpec.getMode(widthMeasureSpec); - final int specHeightSize = MeasureSpec.getSize(heightMeasureSpec); - final int specHeightMode = MeasureSpec.getMode(heightMeasureSpec); - - //We expect to be somewhere inside a MaterialCalendarView, which should measure EXACTLY - if (specHeightMode == MeasureSpec.UNSPECIFIED || specWidthMode == MeasureSpec.UNSPECIFIED) { - throw new IllegalStateException("CalendarPagerView should never be left to decide it's size"); - } - - //The spec width should be a correct multiple - final int measureTileWidth = specWidthSize / DEFAULT_DAYS_IN_WEEK; - final int measureTileHeight = specHeightSize / getRows(); - - //Just use the spec sizes - setMeasuredDimension(specWidthSize, specHeightSize); - - int count = getChildCount(); - - for (int i = 0; i < count; i++) { - final View child = getChildAt(i); - - int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( - measureTileWidth, - MeasureSpec.EXACTLY - ); - - int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( - measureTileHeight, - MeasureSpec.EXACTLY - ); - - child.measure(childWidthMeasureSpec, childHeightMeasureSpec); - } + protected void updateUi() { + for (DayView dayView : dayViews) { + CalendarDay day = dayView.getDate(); + dayView.setupSelection(showOtherDates, day.isInRange(minDate, maxDate), isDayEnabled(day)); } + postInvalidate(); + } - /** - * Return the number of rows to display per page - * - * @return - */ - protected abstract int getRows(); - - /** - * {@inheritDoc} - */ - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - final int parentWidth = getWidth(); - final int count = getChildCount(); - final int parentLeft = 0; - final int parentRight = parentWidth; - - int childTop = 0; - int childLeft = parentLeft; - int childRight = parentRight; - - for (int i = 0; i < count; i++) { - final View child = getChildAt(i); - - final int width = child.getMeasuredWidth(); - final int height = child.getMeasuredHeight(); - - if (LocalUtils.isRTL()) { - child.layout(childRight - width, childTop, childRight, childTop + height); - childRight -= width; - } else { - child.layout(childLeft, childTop, childLeft + width, childTop + height); - childLeft += width; - } - - //We should warp every so many children - if (i % DEFAULT_DAYS_IN_WEEK == (DEFAULT_DAYS_IN_WEEK - 1)) { - childLeft = parentLeft; - childRight = parentRight; - childTop += height; - } - + protected void invalidateDecorators() { + final DayViewFacade facadeAccumulator = new DayViewFacade(); + for (DayView dayView : dayViews) { + facadeAccumulator.reset(); + for (DecoratorResult result : decoratorResults) { + if (result.decorator.shouldDecorate(dayView.getDate())) { + result.result.applyTo(facadeAccumulator); } - } - - /** - * {@inheritDoc} - */ - @Override - public LayoutParams generateLayoutParams(AttributeSet attrs) { - return new LayoutParams(); - } - - @Override - public boolean shouldDelayChildPressedState() { - return false; - } + } + dayView.applyFacade(facadeAccumulator); + } + } + + @Override + public void onClick(final View v) { + if (v instanceof DayView) { + final DayView dayView = (DayView) v; + mcv.onDateClicked(dayView); + } + } + + @Override + public boolean onLongClick(final View v) { + if (v instanceof DayView) { + final DayView dayView = (DayView) v; + mcv.onDateLongClicked(dayView); + return true; + } + return false; + } + + /* + * Custom ViewGroup Code + */ + + /** + * {@inheritDoc} + */ + @Override + protected LayoutParams generateDefaultLayoutParams() { + return new LayoutParams(); + } + + /** + * {@inheritDoc} + */ + @Override + protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { + final int specWidthSize = MeasureSpec.getSize(widthMeasureSpec); + final int specWidthMode = MeasureSpec.getMode(widthMeasureSpec); + final int specHeightSize = MeasureSpec.getSize(heightMeasureSpec); + final int specHeightMode = MeasureSpec.getMode(heightMeasureSpec); + + //We expect to be somewhere inside a MaterialCalendarView, which should measure EXACTLY + if (specHeightMode == MeasureSpec.UNSPECIFIED || specWidthMode == MeasureSpec.UNSPECIFIED) { + throw new IllegalStateException("CalendarPagerView should never be left to decide it's size"); + } + + //The spec width should be a correct multiple + final int measureTileWidth = specWidthSize / DEFAULT_DAYS_IN_WEEK; + final int measureTileHeight = specHeightSize / getRows(); + + //Just use the spec sizes + setMeasuredDimension(specWidthSize, specHeightSize); + + int count = getChildCount(); + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + + int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( + measureTileWidth, + MeasureSpec.EXACTLY + ); + + int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( + measureTileHeight, + MeasureSpec.EXACTLY + ); + + child.measure(childWidthMeasureSpec, childHeightMeasureSpec); + } + } + + /** + * Return the number of rows to display per page + */ + protected abstract int getRows(); + + /** + * {@inheritDoc} + */ + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + final int parentWidth = getWidth(); + final int count = getChildCount(); + final int parentLeft = 0; + final int parentRight = parentWidth; + + int childTop = 0; + int childLeft = parentLeft; + int childRight = parentRight; + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + + final int width = child.getMeasuredWidth(); + final int height = child.getMeasuredHeight(); + + if (LocalUtils.isRTL()) { + child.layout(childRight - width, childTop, childRight, childTop + height); + childRight -= width; + } else { + child.layout(childLeft, childTop, childLeft + width, childTop + height); + childLeft += width; + } + + //We should warp every so many children + if (i % DEFAULT_DAYS_IN_WEEK == (DEFAULT_DAYS_IN_WEEK - 1)) { + childLeft = parentLeft; + childRight = parentRight; + childTop += height; + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public LayoutParams generateLayoutParams(AttributeSet attrs) { + return new LayoutParams(); + } + + @Override + public boolean shouldDelayChildPressedState() { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { + return p instanceof LayoutParams; + } + + @Override + protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { + return new LayoutParams(); + } + + @Override + public void onInitializeAccessibilityEvent(@NonNull AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(event); + event.setClassName(CalendarPagerView.class.getName()); + } + + @Override + public void onInitializeAccessibilityNodeInfo(@NonNull AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName(CalendarPagerView.class.getName()); + } + + protected CalendarDay getFirstViewDay() { + return firstViewDay; + } + + /** + * Simple layout params class for MonthView, since every child is the same size + */ + protected static class LayoutParams extends MarginLayoutParams { /** * {@inheritDoc} */ - @Override - protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { - return p instanceof LayoutParams; - } - - @Override - protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { - return new LayoutParams(); - } - - - @Override - public void onInitializeAccessibilityEvent(@NonNull AccessibilityEvent event) { - super.onInitializeAccessibilityEvent(event); - event.setClassName(CalendarPagerView.class.getName()); - } - - @Override - public void onInitializeAccessibilityNodeInfo(@NonNull AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfo(info); - info.setClassName(CalendarPagerView.class.getName()); - } - - protected CalendarDay getFirstViewDay() { - return firstViewDay; - } - - /** - * Simple layout params class for MonthView, since every child is the same size - */ - protected static class LayoutParams extends MarginLayoutParams { - - /** - * {@inheritDoc} - */ - public LayoutParams() { - super(WRAP_CONTENT, WRAP_CONTENT); - } + public LayoutParams() { + super(WRAP_CONTENT, WRAP_CONTENT); } + } } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/DayView.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/DayView.java index 807c48dd..675e5f94 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/DayView.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/DayView.java @@ -19,11 +19,8 @@ import android.text.Spanned; import android.view.Gravity; import android.view.View; -import android.widget.CheckedTextView; - import com.prolificinteractive.materialcalendarview.MaterialCalendarView.ShowOtherDates; import com.prolificinteractive.materialcalendarview.format.DayFormatter; - import java.util.List; import static com.prolificinteractive.materialcalendarview.MaterialCalendarView.showDecoratedDisabled; @@ -33,269 +30,276 @@ /** * Display one day of a {@linkplain MaterialCalendarView} */ -@SuppressLint("ViewConstructor") -class DayView extends AppCompatCheckedTextView { +@SuppressLint("ViewConstructor") class DayView extends AppCompatCheckedTextView { - private CalendarDay date; - private int selectionColor = Color.GRAY; + private CalendarDay date; + private int selectionColor = Color.GRAY; - private final int fadeTime; - private Drawable customBackground = null; - private Drawable selectionDrawable; - private Drawable mCircleDrawable; - private DayFormatter formatter = DayFormatter.DEFAULT; - private DayFormatter contentDescriptionFormatter = formatter; + private final int fadeTime; + private Drawable customBackground = null; + private Drawable selectionDrawable; + private Drawable mCircleDrawable; + private DayFormatter formatter = DayFormatter.DEFAULT; + private DayFormatter contentDescriptionFormatter = formatter; - private boolean isInRange = true; - private boolean isInMonth = true; - private boolean isDecoratedDisabled = false; - @ShowOtherDates - private int showOtherDates = MaterialCalendarView.SHOW_DEFAULTS; + private boolean isInRange = true; + private boolean isInMonth = true; + private boolean isDecoratedDisabled = false; + @ShowOtherDates + private int showOtherDates = MaterialCalendarView.SHOW_DEFAULTS; - public DayView(Context context, CalendarDay day) { - super(context); + public DayView(Context context, CalendarDay day) { + super(context); - fadeTime = getResources().getInteger(android.R.integer.config_shortAnimTime); + fadeTime = getResources().getInteger(android.R.integer.config_shortAnimTime); - setSelectionColor(this.selectionColor); + setSelectionColor(this.selectionColor); - setGravity(Gravity.CENTER); + setGravity(Gravity.CENTER); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - setTextAlignment(TEXT_ALIGNMENT_CENTER); - } - - setDay(day); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + setTextAlignment(TEXT_ALIGNMENT_CENTER); } - public void setDay(CalendarDay date) { - this.date = date; - setText(getLabel()); + setDay(day); + } + + public void setDay(CalendarDay date) { + this.date = date; + setText(getLabel()); + } + + /** + * Set the new label formatter and reformat the current label. This preserves current spans. + * + * @param formatter new label formatter + */ + public void setDayFormatter(DayFormatter formatter) { + this.contentDescriptionFormatter = contentDescriptionFormatter == this.formatter ? + formatter : contentDescriptionFormatter; + this.formatter = formatter == null ? DayFormatter.DEFAULT : formatter; + CharSequence currentLabel = getText(); + Object[] spans = null; + if (currentLabel instanceof Spanned) { + spans = ((Spanned) currentLabel).getSpans(0, currentLabel.length(), Object.class); } - - /** - * Set the new label formatter and reformat the current label. This preserves current spans. - * - * @param formatter new label formatter - */ - public void setDayFormatter(DayFormatter formatter) { - this.contentDescriptionFormatter = contentDescriptionFormatter == this.formatter ? - formatter : contentDescriptionFormatter; - this.formatter = formatter == null ? DayFormatter.DEFAULT : formatter; - CharSequence currentLabel = getText(); - Object[] spans = null; - if (currentLabel instanceof Spanned) { - spans = ((Spanned) currentLabel).getSpans(0, currentLabel.length(), Object.class); - } - SpannableString newLabel = new SpannableString(getLabel()); - if (spans != null) { - for (Object span : spans) { - newLabel.setSpan(span, 0, newLabel.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } - } - setText(newLabel); + SpannableString newLabel = new SpannableString(getLabel()); + if (spans != null) { + for (Object span : spans) { + newLabel.setSpan(span, 0, newLabel.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } } - - /** - * Set the new content description formatter and reformat the current content description. - * - * @param formatter new content description formatter - */ - public void setDayFormatterContentDescription(DayFormatter formatter) { - this.contentDescriptionFormatter = formatter == null ? this.formatter : formatter; - setContentDescription(getContentDescriptionLabel()); + setText(newLabel); + } + + /** + * Set the new content description formatter and reformat the current content description. + * + * @param formatter new content description formatter + */ + public void setDayFormatterContentDescription(DayFormatter formatter) { + this.contentDescriptionFormatter = formatter == null ? this.formatter : formatter; + setContentDescription(getContentDescriptionLabel()); + } + + @NonNull + public String getLabel() { + return formatter.format(date); + } + + @NonNull + public String getContentDescriptionLabel() { + return contentDescriptionFormatter == null ? formatter.format(date) + : contentDescriptionFormatter.format(date); + } + + public void setSelectionColor(int color) { + this.selectionColor = color; + regenerateBackground(); + } + + /** + * @param drawable custom selection drawable + */ + public void setSelectionDrawable(Drawable drawable) { + if (drawable == null) { + this.selectionDrawable = null; + } else { + this.selectionDrawable = drawable.getConstantState().newDrawable(getResources()); } - - @NonNull - public String getLabel() { - return formatter.format(date); + regenerateBackground(); + } + + /** + * @param drawable background to draw behind everything else + */ + public void setCustomBackground(Drawable drawable) { + if (drawable == null) { + this.customBackground = null; + } else { + this.customBackground = drawable.getConstantState().newDrawable(getResources()); } + invalidate(); + } - @NonNull - public String getContentDescriptionLabel() { - return contentDescriptionFormatter == null ? formatter.format(date) : contentDescriptionFormatter.format(date); - } + public CalendarDay getDate() { + return date; + } - public void setSelectionColor(int color) { - this.selectionColor = color; - regenerateBackground(); - } + private void setEnabled() { + boolean enabled = isInMonth && isInRange && !isDecoratedDisabled; + super.setEnabled(isInRange && !isDecoratedDisabled); - /** - * @param drawable custom selection drawable - */ - public void setSelectionDrawable(Drawable drawable) { - if (drawable == null) { - this.selectionDrawable = null; - } else { - this.selectionDrawable = drawable.getConstantState().newDrawable(getResources()); - } - regenerateBackground(); - } + boolean showOtherMonths = showOtherMonths(showOtherDates); + boolean showOutOfRange = showOutOfRange(showOtherDates) || showOtherMonths; + boolean showDecoratedDisabled = showDecoratedDisabled(showOtherDates); - /** - * @param drawable background to draw behind everything else - */ - public void setCustomBackground(Drawable drawable) { - if (drawable == null) { - this.customBackground = null; - } else { - this.customBackground = drawable.getConstantState().newDrawable(getResources()); - } - invalidate(); - } + boolean shouldBeVisible = enabled; - public CalendarDay getDate() { - return date; + if (!isInMonth && showOtherMonths) { + shouldBeVisible = true; } - private void setEnabled() { - boolean enabled = isInMonth && isInRange && !isDecoratedDisabled; - super.setEnabled(isInRange && !isDecoratedDisabled); - - boolean showOtherMonths = showOtherMonths(showOtherDates); - boolean showOutOfRange = showOutOfRange(showOtherDates) || showOtherMonths; - boolean showDecoratedDisabled = showDecoratedDisabled(showOtherDates); - - boolean shouldBeVisible = enabled; - - if (!isInMonth && showOtherMonths) { - shouldBeVisible = true; - } - - if (!isInRange && showOutOfRange) { - shouldBeVisible |= isInMonth; - } - - if (isDecoratedDisabled && showDecoratedDisabled) { - shouldBeVisible |= isInMonth && isInRange; - } - - if (!isInMonth && shouldBeVisible) { - setTextColor(getTextColors().getColorForState( - new int[]{-android.R.attr.state_enabled}, Color.GRAY)); - } - setVisibility(shouldBeVisible ? View.VISIBLE : View.INVISIBLE); + if (!isInRange && showOutOfRange) { + shouldBeVisible |= isInMonth; } - protected void setupSelection(@ShowOtherDates int showOtherDates, boolean inRange, boolean inMonth) { - this.showOtherDates = showOtherDates; - this.isInMonth = inMonth; - this.isInRange = inRange; - setEnabled(); + if (isDecoratedDisabled && showDecoratedDisabled) { + shouldBeVisible |= isInMonth && isInRange; } - private final Rect tempRect = new Rect(); - private final Rect circleDrawableRect = new Rect(); - - @Override - protected void onDraw(@NonNull Canvas canvas) { - if (customBackground != null) { - customBackground.setBounds(tempRect); - customBackground.setState(getDrawableState()); - customBackground.draw(canvas); - } - - mCircleDrawable.setBounds(circleDrawableRect); - - super.onDraw(canvas); + if (!isInMonth && shouldBeVisible) { + setTextColor(getTextColors().getColorForState( + new int[] { -android.R.attr.state_enabled }, Color.GRAY)); } - - private void regenerateBackground() { - if (selectionDrawable != null) { - setBackgroundDrawable(selectionDrawable); - } else { - mCircleDrawable = generateBackground(selectionColor, fadeTime, circleDrawableRect); - setBackgroundDrawable(mCircleDrawable); - } + setVisibility(shouldBeVisible ? View.VISIBLE : View.INVISIBLE); + } + + protected void setupSelection( + @ShowOtherDates int showOtherDates, + boolean inRange, + boolean inMonth) { + this.showOtherDates = showOtherDates; + this.isInMonth = inMonth; + this.isInRange = inRange; + setEnabled(); + } + + private final Rect tempRect = new Rect(); + private final Rect circleDrawableRect = new Rect(); + + @Override + protected void onDraw(@NonNull Canvas canvas) { + if (customBackground != null) { + customBackground.setBounds(tempRect); + customBackground.setState(getDrawableState()); + customBackground.draw(canvas); } - private static Drawable generateBackground(int color, int fadeTime, Rect bounds) { - StateListDrawable drawable = new StateListDrawable(); - drawable.setExitFadeDuration(fadeTime); - drawable.addState(new int[]{android.R.attr.state_checked}, generateCircleDrawable(color)); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - drawable.addState(new int[]{android.R.attr.state_pressed}, generateRippleDrawable(color, bounds)); - } else { - drawable.addState(new int[]{android.R.attr.state_pressed}, generateCircleDrawable(color)); - } + mCircleDrawable.setBounds(circleDrawableRect); - drawable.addState(new int[]{}, generateCircleDrawable(Color.TRANSPARENT)); + super.onDraw(canvas); + } - return drawable; + private void regenerateBackground() { + if (selectionDrawable != null) { + setBackgroundDrawable(selectionDrawable); + } else { + mCircleDrawable = generateBackground(selectionColor, fadeTime, circleDrawableRect); + setBackgroundDrawable(mCircleDrawable); } - - private static Drawable generateCircleDrawable(final int color) { - ShapeDrawable drawable = new ShapeDrawable(new OvalShape()); - drawable.getPaint().setColor(color); - return drawable; + } + + private static Drawable generateBackground(int color, int fadeTime, Rect bounds) { + StateListDrawable drawable = new StateListDrawable(); + drawable.setExitFadeDuration(fadeTime); + drawable.addState(new int[] { android.R.attr.state_checked }, generateCircleDrawable(color)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + drawable.addState( + new int[] { android.R.attr.state_pressed }, + generateRippleDrawable(color, bounds) + ); + } else { + drawable.addState(new int[] { android.R.attr.state_pressed }, generateCircleDrawable(color)); } - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - private static Drawable generateRippleDrawable(final int color, Rect bounds) { - ColorStateList list = ColorStateList.valueOf(color); - Drawable mask = generateCircleDrawable(Color.WHITE); - RippleDrawable rippleDrawable = new RippleDrawable(list, null, mask); -// API 21 - if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) { - rippleDrawable.setBounds(bounds); - } - -// API 22. Technically harmless to leave on for API 21 and 23, but not worth risking for 23+ - if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1) { - int center = (bounds.left + bounds.right) / 2; - rippleDrawable.setHotspotBounds(center, bounds.top, center, bounds.bottom); - } - - return rippleDrawable; + drawable.addState(new int[] { }, generateCircleDrawable(Color.TRANSPARENT)); + + return drawable; + } + + private static Drawable generateCircleDrawable(final int color) { + ShapeDrawable drawable = new ShapeDrawable(new OvalShape()); + drawable.getPaint().setColor(color); + return drawable; + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + private static Drawable generateRippleDrawable(final int color, Rect bounds) { + ColorStateList list = ColorStateList.valueOf(color); + Drawable mask = generateCircleDrawable(Color.WHITE); + RippleDrawable rippleDrawable = new RippleDrawable(list, null, mask); + // API 21 + if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) { + rippleDrawable.setBounds(bounds); } - /** - * @param facade apply the facade to us - */ - void applyFacade(DayViewFacade facade) { - this.isDecoratedDisabled = facade.areDaysDisabled(); - setEnabled(); - - setCustomBackground(facade.getBackgroundDrawable()); - setSelectionDrawable(facade.getSelectionDrawable()); - - // Facade has spans - List spans = facade.getSpans(); - if (!spans.isEmpty()) { - String label = getLabel(); - SpannableString formattedLabel = new SpannableString(getLabel()); - for (DayViewFacade.Span span : spans) { - formattedLabel.setSpan(span.span, 0, label.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } - setText(formattedLabel); - } - // Reset in case it was customized previously - else { - setText(getLabel()); - } + // API 22. Technically harmless to leave on for API 21 and 23, but not worth risking for 23+ + if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1) { + int center = (bounds.left + bounds.right) / 2; + rippleDrawable.setHotspotBounds(center, bounds.top, center, bounds.bottom); } - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - calculateBounds(right - left, bottom - top); - regenerateBackground(); + return rippleDrawable; + } + + /** + * @param facade apply the facade to us + */ + void applyFacade(DayViewFacade facade) { + this.isDecoratedDisabled = facade.areDaysDisabled(); + setEnabled(); + + setCustomBackground(facade.getBackgroundDrawable()); + setSelectionDrawable(facade.getSelectionDrawable()); + + // Facade has spans + List spans = facade.getSpans(); + if (!spans.isEmpty()) { + String label = getLabel(); + SpannableString formattedLabel = new SpannableString(getLabel()); + for (DayViewFacade.Span span : spans) { + formattedLabel.setSpan(span.span, 0, label.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + setText(formattedLabel); } - - private void calculateBounds(int width, int height) { - final int radius = Math.min(height, width); - final int offset = Math.abs(height - width) / 2; - - // Lollipop platform bug. Circle drawable offset needs to be half of normal offset - final int circleOffset = Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP ? offset / 2 : offset; - - if (width >= height) { - tempRect.set(offset, 0, radius + offset, height); - circleDrawableRect.set(circleOffset, 0, radius + circleOffset, height); - } else { - tempRect.set(0, offset, width, radius + offset); - circleDrawableRect.set(0, circleOffset, width, radius + circleOffset); - } + // Reset in case it was customized previously + else { + setText(getLabel()); + } + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + calculateBounds(right - left, bottom - top); + regenerateBackground(); + } + + private void calculateBounds(int width, int height) { + final int radius = Math.min(height, width); + final int offset = Math.abs(height - width) / 2; + + // Lollipop platform bug. Circle drawable offset needs to be half of normal offset + final int circleOffset = + Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP ? offset / 2 : offset; + + if (width >= height) { + tempRect.set(offset, 0, radius + offset, height); + circleDrawableRect.set(circleOffset, 0, radius + circleOffset, height); + } else { + tempRect.set(0, offset, width, radius + offset); + circleDrawableRect.set(0, circleOffset, width, radius + circleOffset); } + } } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/DayViewDecorator.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/DayViewDecorator.java index 21420bce..4b7585c1 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/DayViewDecorator.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/DayViewDecorator.java @@ -5,19 +5,18 @@ */ public interface DayViewDecorator { - /** - * Determine if a specific day should be decorated - * - * @param day {@linkplain CalendarDay} to possibly decorate - * @return true if this decorator should be applied to the provided day - */ - boolean shouldDecorate(CalendarDay day); - - /** - * Set decoration options onto a facade to be applied to all relevant days - * - * @param view View to decorate - */ - void decorate(DayViewFacade view); + /** + * Determine if a specific day should be decorated + * + * @param day {@linkplain CalendarDay} to possibly decorate + * @return true if this decorator should be applied to the provided day + */ + boolean shouldDecorate(CalendarDay day); + /** + * Set decoration options onto a facade to be applied to all relevant days + * + * @param view View to decorate + */ + void decorate(DayViewFacade view); } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/DayViewFacade.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/DayViewFacade.java index a4eeb71d..cbffdfec 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/DayViewFacade.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/DayViewFacade.java @@ -2,7 +2,6 @@ import android.graphics.drawable.Drawable; import android.support.annotation.NonNull; - import java.util.Collections; import java.util.LinkedList; import java.util.List; @@ -12,124 +11,124 @@ */ public class DayViewFacade { - private boolean isDecorated; - - private Drawable backgroundDrawable = null; - private Drawable selectionDrawable = null; - private final LinkedList spans = new LinkedList<>(); - private boolean daysDisabled = false; - - DayViewFacade() { - isDecorated = false; - } - - /** - * Set a drawable to draw behind everything else - * - * @param drawable Drawable to draw behind everything - */ - public void setBackgroundDrawable(@NonNull Drawable drawable) { - if (drawable == null) { - throw new IllegalArgumentException("Cannot be null"); - } - this.backgroundDrawable = drawable; - isDecorated = true; - } - - /** - * Set a custom selection drawable - * TODO: define states that can/should be used in StateListDrawables - * - * @param drawable the drawable for selection - */ - public void setSelectionDrawable(@NonNull Drawable drawable) { - if (drawable == null) { - throw new IllegalArgumentException("Cannot be null"); - } - selectionDrawable = drawable; - isDecorated = true; - } - - /** - * Add a span to the entire text of a day - * - * @param span text span instance - */ - public void addSpan(@NonNull Object span) { - if (spans != null) { - this.spans.add(new Span(span)); - isDecorated = true; - } - } - - /** - *

Set days to be in a disabled state, or re-enabled.

- *

Note, passing true here will not override minimum and maximum dates, if set. - * This will only re-enable disabled dates.

- * - * @param daysDisabled true to disable days, false to re-enable days - */ - public void setDaysDisabled(boolean daysDisabled) { - this.daysDisabled = daysDisabled; - this.isDecorated = true; - } - - void reset() { - backgroundDrawable = null; - selectionDrawable = null; - spans.clear(); - isDecorated = false; - daysDisabled = false; - } - - /** - * Apply things set this to other - * - * @param other facade to apply our data to - */ - void applyTo(DayViewFacade other) { - if (selectionDrawable != null) { - other.setSelectionDrawable(selectionDrawable); - } - if (backgroundDrawable != null) { - other.setBackgroundDrawable(backgroundDrawable); - } - other.spans.addAll(spans); - other.isDecorated |= this.isDecorated; - other.daysDisabled = daysDisabled; + private boolean isDecorated; + + private Drawable backgroundDrawable = null; + private Drawable selectionDrawable = null; + private final LinkedList spans = new LinkedList<>(); + private boolean daysDisabled = false; + + DayViewFacade() { + isDecorated = false; + } + + /** + * Set a drawable to draw behind everything else + * + * @param drawable Drawable to draw behind everything + */ + public void setBackgroundDrawable(@NonNull Drawable drawable) { + if (drawable == null) { + throw new IllegalArgumentException("Cannot be null"); } - - boolean isDecorated() { - return isDecorated; - } - - Drawable getSelectionDrawable() { - return selectionDrawable; + this.backgroundDrawable = drawable; + isDecorated = true; + } + + /** + * Set a custom selection drawable + * TODO: define states that can/should be used in StateListDrawables + * + * @param drawable the drawable for selection + */ + public void setSelectionDrawable(@NonNull Drawable drawable) { + if (drawable == null) { + throw new IllegalArgumentException("Cannot be null"); } - - Drawable getBackgroundDrawable() { - return backgroundDrawable; + selectionDrawable = drawable; + isDecorated = true; + } + + /** + * Add a span to the entire text of a day + * + * @param span text span instance + */ + public void addSpan(@NonNull Object span) { + if (spans != null) { + this.spans.add(new Span(span)); + isDecorated = true; } - - List getSpans() { - return Collections.unmodifiableList(spans); + } + + /** + *

Set days to be in a disabled state, or re-enabled.

+ *

Note, passing true here will not override minimum and maximum dates, if set. + * This will only re-enable disabled dates.

+ * + * @param daysDisabled true to disable days, false to re-enable days + */ + public void setDaysDisabled(boolean daysDisabled) { + this.daysDisabled = daysDisabled; + this.isDecorated = true; + } + + void reset() { + backgroundDrawable = null; + selectionDrawable = null; + spans.clear(); + isDecorated = false; + daysDisabled = false; + } + + /** + * Apply things set this to other + * + * @param other facade to apply our data to + */ + void applyTo(DayViewFacade other) { + if (selectionDrawable != null) { + other.setSelectionDrawable(selectionDrawable); } - - /** - * Are days from this facade disabled - * - * @return true if disabled, false if not re-enabled - */ - public boolean areDaysDisabled() { - return daysDisabled; + if (backgroundDrawable != null) { + other.setBackgroundDrawable(backgroundDrawable); } - - static class Span { - - final Object span; - - public Span(Object span) { - this.span = span; - } + other.spans.addAll(spans); + other.isDecorated |= this.isDecorated; + other.daysDisabled = daysDisabled; + } + + boolean isDecorated() { + return isDecorated; + } + + Drawable getSelectionDrawable() { + return selectionDrawable; + } + + Drawable getBackgroundDrawable() { + return backgroundDrawable; + } + + List getSpans() { + return Collections.unmodifiableList(spans); + } + + /** + * Are days from this facade disabled + * + * @return true if disabled, false if not re-enabled + */ + public boolean areDaysDisabled() { + return daysDisabled; + } + + static class Span { + + final Object span; + + public Span(Object span) { + this.span = span; } + } } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/DecoratorResult.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/DecoratorResult.java index d491a955..392897f3 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/DecoratorResult.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/DecoratorResult.java @@ -1,11 +1,11 @@ package com.prolificinteractive.materialcalendarview; class DecoratorResult { - public final DayViewDecorator decorator; - public final DayViewFacade result; + public final DayViewDecorator decorator; + public final DayViewFacade result; - DecoratorResult(DayViewDecorator decorator, DayViewFacade result) { - this.decorator = decorator; - this.result = result; - } + DecoratorResult(DayViewDecorator decorator, DayViewFacade result) { + this.decorator = decorator; + this.result = result; + } } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/DirectionButton.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/DirectionButton.java index 1edf8e7f..9c9fffc7 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/DirectionButton.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/DirectionButton.java @@ -12,37 +12,37 @@ */ class DirectionButton extends ImageView { - public DirectionButton(Context context) { - super(context); - - setBackgroundResource(getThemeSelectableBackgroundId(context)); - } - - public void setColor(int color) { - setColorFilter(color, PorterDuff.Mode.SRC_ATOP); + public DirectionButton(Context context) { + super(context); + + setBackgroundResource(getThemeSelectableBackgroundId(context)); + } + + public void setColor(int color) { + setColorFilter(color, PorterDuff.Mode.SRC_ATOP); + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + setAlpha(enabled ? 1f : 0.1f); + } + + private static int getThemeSelectableBackgroundId(Context context) { + //Get selectableItemBackgroundBorderless defined for AppCompat + int colorAttr = context.getResources().getIdentifier( + "selectableItemBackgroundBorderless", "attr", context.getPackageName()); + + if (colorAttr == 0) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + colorAttr = android.R.attr.selectableItemBackgroundBorderless; + } else { + colorAttr = android.R.attr.selectableItemBackground; + } } - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - setAlpha(enabled ? 1f : 0.1f); - } - - private static int getThemeSelectableBackgroundId(Context context) { - //Get selectableItemBackgroundBorderless defined for AppCompat - int colorAttr = context.getResources().getIdentifier( - "selectableItemBackgroundBorderless", "attr", context.getPackageName()); - - if (colorAttr == 0) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - colorAttr = android.R.attr.selectableItemBackgroundBorderless; - } else { - colorAttr = android.R.attr.selectableItemBackground; - } - } - - TypedValue outValue = new TypedValue(); - context.getTheme().resolveAttribute(colorAttr, outValue, true); - return outValue.resourceId; - } + TypedValue outValue = new TypedValue(); + context.getTheme().resolveAttribute(colorAttr, outValue, true); + return outValue.resourceId; + } } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/MaterialCalendarView.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/MaterialCalendarView.java index 9bde64da..c20dfd4d 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/MaterialCalendarView.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/MaterialCalendarView.java @@ -26,13 +26,11 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; - import com.prolificinteractive.materialcalendarview.format.ArrayWeekDayFormatter; import com.prolificinteractive.materialcalendarview.format.DayFormatter; import com.prolificinteractive.materialcalendarview.format.MonthArrayTitleFormatter; import com.prolificinteractive.materialcalendarview.format.TitleFormatter; import com.prolificinteractive.materialcalendarview.format.WeekDayFormatter; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -69,144 +67,147 @@ */ public class MaterialCalendarView extends ViewGroup { - public static final int INVALID_TILE_DIMENSION = -10; - - /** - * {@linkplain IntDef} annotation for selection mode. - * - * @see #setSelectionMode(int) - * @see #getSelectionMode() - */ - @Retention(RetentionPolicy.SOURCE) - @IntDef({SELECTION_MODE_NONE, SELECTION_MODE_SINGLE, SELECTION_MODE_MULTIPLE, SELECTION_MODE_RANGE}) - public @interface SelectionMode { - } - - /** - * Selection mode that disallows all selection. - * When changing to this mode, current selection will be cleared. - */ - public static final int SELECTION_MODE_NONE = 0; - - /** - * Selection mode that allows one selected date at one time. This is the default mode. - * When switching from {@linkplain #SELECTION_MODE_MULTIPLE}, this will select the same date - * as from {@linkplain #getSelectedDate()}, which should be the last selected date - */ - public static final int SELECTION_MODE_SINGLE = 1; - - /** - * Selection mode which allows more than one selected date at one time. - */ - public static final int SELECTION_MODE_MULTIPLE = 2; - - /** - * Selection mode which allows selection of a range between two dates - */ - public static final int SELECTION_MODE_RANGE = 3; - - /** - * {@linkplain IntDef} annotation for showOtherDates. - * - * @see #setShowOtherDates(int) - * @see #getShowOtherDates() - */ - @SuppressLint("UniqueConstants") - @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = true, value = { - SHOW_NONE, SHOW_ALL, SHOW_DEFAULTS, - SHOW_OUT_OF_RANGE, SHOW_OTHER_MONTHS, SHOW_DECORATED_DISABLED - }) - public @interface ShowOtherDates { + public static final int INVALID_TILE_DIMENSION = -10; + + /** + * {@linkplain IntDef} annotation for selection mode. + * + * @see #setSelectionMode(int) + * @see #getSelectionMode() + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef( + { SELECTION_MODE_NONE, SELECTION_MODE_SINGLE, SELECTION_MODE_MULTIPLE, SELECTION_MODE_RANGE }) + public @interface SelectionMode { + } + + /** + * Selection mode that disallows all selection. + * When changing to this mode, current selection will be cleared. + */ + public static final int SELECTION_MODE_NONE = 0; + + /** + * Selection mode that allows one selected date at one time. This is the default mode. + * When switching from {@linkplain #SELECTION_MODE_MULTIPLE}, this will select the same date + * as from {@linkplain #getSelectedDate()}, which should be the last selected date + */ + public static final int SELECTION_MODE_SINGLE = 1; + + /** + * Selection mode which allows more than one selected date at one time. + */ + public static final int SELECTION_MODE_MULTIPLE = 2; + + /** + * Selection mode which allows selection of a range between two dates + */ + public static final int SELECTION_MODE_RANGE = 3; + + /** + * {@linkplain IntDef} annotation for showOtherDates. + * + * @see #setShowOtherDates(int) + * @see #getShowOtherDates() + */ + @SuppressLint("UniqueConstants") + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, value = { + SHOW_NONE, SHOW_ALL, SHOW_DEFAULTS, + SHOW_OUT_OF_RANGE, SHOW_OTHER_MONTHS, SHOW_DECORATED_DISABLED + }) + public @interface ShowOtherDates { + } + + /** + * Do not show any non-enabled dates + */ + public static final int SHOW_NONE = 0; + + /** + * Show dates from the proceeding and successive months, in a disabled state. + * This flag also enables the {@link #SHOW_OUT_OF_RANGE} flag to prevent odd blank areas. + */ + public static final int SHOW_OTHER_MONTHS = 1; + + /** + * Show dates that are outside of the min-max range. + * This will only show days from the current month unless {@link #SHOW_OTHER_MONTHS} is enabled. + */ + public static final int SHOW_OUT_OF_RANGE = 1 << 1; + + /** + * Show days that are individually disabled with decorators. + * This will only show dates in the current month and inside the minimum and maximum date range. + */ + public static final int SHOW_DECORATED_DISABLED = 1 << 2; + + /** + * The default flags for showing non-enabled dates. Currently only shows {@link #SHOW_DECORATED_DISABLED} + */ + public static final int SHOW_DEFAULTS = SHOW_DECORATED_DISABLED; + + /** + * Show all the days + */ + public static final int SHOW_ALL = + SHOW_OTHER_MONTHS | SHOW_OUT_OF_RANGE | SHOW_DECORATED_DISABLED; + + /** + * Use this orientation to animate the title vertically + */ + public static final int VERTICAL = 0; + + /** + * Use this orientation to animate the title horizontally + */ + public static final int HORIZONTAL = 1; + + /** + * Default tile size in DIPs. This is used in cases where there is no tile size specificed and the view is set to {@linkplain ViewGroup.LayoutParams#WRAP_CONTENT WRAP_CONTENT} + */ + public static final int DEFAULT_TILE_SIZE_DP = 44; + private static final int DEFAULT_DAYS_IN_WEEK = 7; + private static final int DEFAULT_MAX_WEEKS = 6; + private static final int DAY_NAMES_ROW = 1; + + private final TitleChanger titleChanger; + + private final TextView title; + private final DirectionButton buttonPast; + private final DirectionButton buttonFuture; + private final CalendarPager pager; + private CalendarPagerAdapter adapter; + private CalendarDay currentMonth; + private LinearLayout topbar; + private CalendarMode calendarMode; + /** + * Used for the dynamic calendar height. + */ + private boolean mDynamicHeightEnabled; + + private final ArrayList dayViewDecorators = new ArrayList<>(); + + private final OnClickListener onClickListener = new OnClickListener() { + @Override + public void onClick(View v) { + if (v == buttonFuture) { + pager.setCurrentItem(pager.getCurrentItem() + 1, true); + } else if (v == buttonPast) { + pager.setCurrentItem(pager.getCurrentItem() - 1, true); + } } + }; - /** - * Do not show any non-enabled dates - */ - public static final int SHOW_NONE = 0; - - /** - * Show dates from the proceeding and successive months, in a disabled state. - * This flag also enables the {@link #SHOW_OUT_OF_RANGE} flag to prevent odd blank areas. - */ - public static final int SHOW_OTHER_MONTHS = 1; - - /** - * Show dates that are outside of the min-max range. - * This will only show days from the current month unless {@link #SHOW_OTHER_MONTHS} is enabled. - */ - public static final int SHOW_OUT_OF_RANGE = 1 << 1; - - /** - * Show days that are individually disabled with decorators. - * This will only show dates in the current month and inside the minimum and maximum date range. - */ - public static final int SHOW_DECORATED_DISABLED = 1 << 2; - - /** - * The default flags for showing non-enabled dates. Currently only shows {@link #SHOW_DECORATED_DISABLED} - */ - public static final int SHOW_DEFAULTS = SHOW_DECORATED_DISABLED; - - /** - * Show all the days - */ - public static final int SHOW_ALL = SHOW_OTHER_MONTHS | SHOW_OUT_OF_RANGE | SHOW_DECORATED_DISABLED; - - /** - * Use this orientation to animate the title vertically - */ - public static final int VERTICAL = 0; - - /** - * Use this orientation to animate the title horizontally - */ - public static final int HORIZONTAL = 1; - - /** - * Default tile size in DIPs. This is used in cases where there is no tile size specificed and the view is set to {@linkplain ViewGroup.LayoutParams#WRAP_CONTENT WRAP_CONTENT} - */ - public static final int DEFAULT_TILE_SIZE_DP = 44; - private static final int DEFAULT_DAYS_IN_WEEK = 7; - private static final int DEFAULT_MAX_WEEKS = 6; - private static final int DAY_NAMES_ROW = 1; - - private final TitleChanger titleChanger; - - private final TextView title; - private final DirectionButton buttonPast; - private final DirectionButton buttonFuture; - private final CalendarPager pager; - private CalendarPagerAdapter adapter; - private CalendarDay currentMonth; - private LinearLayout topbar; - private CalendarMode calendarMode; - /** - * Used for the dynamic calendar height. - */ - private boolean mDynamicHeightEnabled; - - private final ArrayList dayViewDecorators = new ArrayList<>(); - - private final OnClickListener onClickListener = new OnClickListener() { - @Override - public void onClick(View v) { - if (v == buttonFuture) { - pager.setCurrentItem(pager.getCurrentItem() + 1, true); - } else if (v == buttonPast) { - pager.setCurrentItem(pager.getCurrentItem() - 1, true); - } - } - }; - - private final ViewPager.OnPageChangeListener pageChangeListener = new ViewPager.OnPageChangeListener() { + private final ViewPager.OnPageChangeListener pageChangeListener = + new ViewPager.OnPageChangeListener() { @Override public void onPageSelected(int position) { - titleChanger.setPreviousMonth(currentMonth); - currentMonth = adapter.getItem(position); - updateUi(); + titleChanger.setPreviousMonth(currentMonth); + currentMonth = adapter.getItem(position); + updateUi(); - dispatchOnMonthChanged(currentMonth); + dispatchOnMonthChanged(currentMonth); } @Override @@ -216,1865 +217,1870 @@ public void onPageScrollStateChanged(int state) { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } - }; - - private CalendarDay minDate = null; - private CalendarDay maxDate = null; - - private OnDateSelectedListener listener; - private OnDateLongClickListener longClickListener; - private OnMonthChangedListener monthListener; - private OnRangeSelectedListener rangeListener; - - CharSequence calendarContentDescription; - private int accentColor = 0; - private int arrowColor = Color.BLACK; - private Drawable leftArrowMask; - private Drawable rightArrowMask; - private int tileHeight = INVALID_TILE_DIMENSION; - private int tileWidth = INVALID_TILE_DIMENSION; - @SelectionMode - private int selectionMode = SELECTION_MODE_SINGLE; - private boolean allowClickDaysOutsideCurrentMonth = true; - private DayOfWeek firstDayOfWeek; - private boolean showWeekDays; - - private State state; - - public MaterialCalendarView(Context context) { - this(context, null); - } - - public MaterialCalendarView(Context context, AttributeSet attrs) { - super(context, attrs); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - //If we're on good Android versions, turn off clipping for cool effects - setClipToPadding(false); - setClipChildren(false); - } else { - //Old Android does not like _not_ clipping view pagers, we need to clip - setClipChildren(true); - setClipToPadding(true); - } - - buttonPast = new DirectionButton(getContext()); - buttonPast.setContentDescription(getContext().getString(R.string.previous)); - title = new AppCompatTextView(getContext()); - buttonFuture = new DirectionButton(getContext()); - buttonFuture.setContentDescription(getContext().getString(R.string.next)); - pager = new CalendarPager(getContext()); - - buttonPast.setOnClickListener(onClickListener); - buttonFuture.setOnClickListener(onClickListener); - - titleChanger = new TitleChanger(title); - - pager.setOnPageChangeListener(pageChangeListener); - pager.setPageTransformer(false, new ViewPager.PageTransformer() { - @Override - public void transformPage(View page, float position) { - position = (float) Math.sqrt(1 - Math.abs(position)); - page.setAlpha(position); - } - }); - - TypedArray a = context.getTheme() - .obtainStyledAttributes(attrs, R.styleable.MaterialCalendarView, 0, 0); - try { - int calendarModeIndex = a.getInteger( - R.styleable.MaterialCalendarView_mcv_calendarMode, - 0 - ); - int firstDayOfWeekInt = a.getInteger( - R.styleable.MaterialCalendarView_mcv_firstDayOfWeek, - -1 - ); - - titleChanger.setOrientation( - a.getInteger(R.styleable.MaterialCalendarView_mcv_titleAnimationOrientation, - VERTICAL)); - - if (firstDayOfWeekInt >= 1 && firstDayOfWeekInt <= 7) { - firstDayOfWeek = DayOfWeek.of(firstDayOfWeekInt); - } else { - firstDayOfWeek = WeekFields.of(Locale.getDefault()).getFirstDayOfWeek(); - } - - showWeekDays = a.getBoolean(R.styleable.MaterialCalendarView_mcv_showWeekDays, true); - - newState() - .setFirstDayOfWeek(firstDayOfWeek) - .setCalendarDisplayMode(CalendarMode.values()[calendarModeIndex]) - .setShowWeekDays(showWeekDays) - .commit(); - - setSelectionMode(a.getInteger( - R.styleable.MaterialCalendarView_mcv_selectionMode, - SELECTION_MODE_SINGLE - )); - - final int tileSize = a.getLayoutDimension(R.styleable.MaterialCalendarView_mcv_tileSize, INVALID_TILE_DIMENSION); - if (tileSize > INVALID_TILE_DIMENSION) { - setTileSize(tileSize); - } - - final int tileWidth = a.getLayoutDimension(R.styleable.MaterialCalendarView_mcv_tileWidth, INVALID_TILE_DIMENSION); - if (tileWidth > INVALID_TILE_DIMENSION) { - setTileWidth(tileWidth); - } - - final int tileHeight = a.getLayoutDimension(R.styleable.MaterialCalendarView_mcv_tileHeight, INVALID_TILE_DIMENSION); - if (tileHeight > INVALID_TILE_DIMENSION) { - setTileHeight(tileHeight); - } - - setArrowColor(a.getColor( - R.styleable.MaterialCalendarView_mcv_arrowColor, - Color.BLACK - )); - Drawable leftMask = a.getDrawable( - R.styleable.MaterialCalendarView_mcv_leftArrowMask - ); - if (leftMask == null) { - leftMask = getResources().getDrawable(R.drawable.mcv_action_previous); - } - setLeftArrowMask(leftMask); - Drawable rightMask = a.getDrawable( - R.styleable.MaterialCalendarView_mcv_rightArrowMask - ); - if (rightMask == null) { - rightMask = getResources().getDrawable(R.drawable.mcv_action_next); - } - setRightArrowMask(rightMask); - - setSelectionColor( - a.getColor( - R.styleable.MaterialCalendarView_mcv_selectionColor, - getThemeAccentColor(context) - ) - ); - - CharSequence[] array = a.getTextArray(R.styleable.MaterialCalendarView_mcv_weekDayLabels); - if (array != null) { - setWeekDayFormatter(new ArrayWeekDayFormatter(array)); - } - - array = a.getTextArray(R.styleable.MaterialCalendarView_mcv_monthLabels); - if (array != null) { - setTitleFormatter(new MonthArrayTitleFormatter(array)); - } - - setHeaderTextAppearance(a.getResourceId( - R.styleable.MaterialCalendarView_mcv_headerTextAppearance, - R.style.TextAppearance_MaterialCalendarWidget_Header - )); - setWeekDayTextAppearance(a.getResourceId( - R.styleable.MaterialCalendarView_mcv_weekDayTextAppearance, - R.style.TextAppearance_MaterialCalendarWidget_WeekDay - )); - setDateTextAppearance(a.getResourceId( - R.styleable.MaterialCalendarView_mcv_dateTextAppearance, - R.style.TextAppearance_MaterialCalendarWidget_Date - )); - //noinspection ResourceType - setShowOtherDates(a.getInteger( - R.styleable.MaterialCalendarView_mcv_showOtherDates, - SHOW_DEFAULTS - )); - - setAllowClickDaysOutsideCurrentMonth(a.getBoolean( - R.styleable.MaterialCalendarView_mcv_allowClickDaysOutsideCurrentMonth, - true - )); - } catch (Exception e) { - e.printStackTrace(); - } finally { - a.recycle(); - } - - // Adapter is created while parsing the TypedArray attrs, so setup has to happen after - setupChildren(); - - currentMonth = CalendarDay.today(); - setCurrentDate(currentMonth); - - if (isInEditMode()) { - removeView(pager); - MonthView monthView = new MonthView(this, currentMonth, getFirstDayOfWeek(), true); - monthView.setSelectionColor(getSelectionColor()); - monthView.setDateTextAppearance(adapter.getDateTextAppearance()); - monthView.setWeekDayTextAppearance(adapter.getWeekDayTextAppearance()); - monthView.setShowOtherDates(getShowOtherDates()); - addView(monthView, new LayoutParams(calendarMode.visibleWeeksCount + DAY_NAMES_ROW)); - } - } - - private void setupChildren() { - topbar = new LinearLayout(getContext()); - topbar.setOrientation(LinearLayout.HORIZONTAL); - topbar.setClipChildren(false); - topbar.setClipToPadding(false); - addView(topbar, new LayoutParams(1)); - - buttonPast.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - topbar.addView(buttonPast, new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1)); - - title.setGravity(Gravity.CENTER); - topbar.addView(title, new LinearLayout.LayoutParams( - 0, LayoutParams.MATCH_PARENT, DEFAULT_DAYS_IN_WEEK - 2 - )); - - buttonFuture.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - topbar.addView(buttonFuture, new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1)); - - pager.setId(R.id.mcv_pager); - pager.setOffscreenPageLimit(1); - int tileHeight = showWeekDays ? calendarMode.visibleWeeksCount + DAY_NAMES_ROW : calendarMode.visibleWeeksCount; - addView(pager, new LayoutParams(tileHeight)); - } - - private void updateUi() { - titleChanger.change(currentMonth); - buttonPast.setEnabled(canGoBack()); - buttonFuture.setEnabled(canGoForward()); - } - - /** - * Change the selection mode of the calendar. The default mode is {@linkplain #SELECTION_MODE_SINGLE} - * - * @param mode the selection mode to change to. This must be one of - * {@linkplain #SELECTION_MODE_NONE}, {@linkplain #SELECTION_MODE_SINGLE}, - * {@linkplain #SELECTION_MODE_RANGE} or {@linkplain #SELECTION_MODE_MULTIPLE}. - * Unknown values will act as {@linkplain #SELECTION_MODE_SINGLE} - * @see #getSelectionMode() - * @see #SELECTION_MODE_NONE - * @see #SELECTION_MODE_SINGLE - * @see #SELECTION_MODE_MULTIPLE - * @see #SELECTION_MODE_RANGE - */ - public void setSelectionMode(final @SelectionMode int mode) { - final @SelectionMode int oldMode = this.selectionMode; - this.selectionMode = mode; - switch (mode) { - case SELECTION_MODE_RANGE: - clearSelection(); - break; - case SELECTION_MODE_MULTIPLE: - break; - case SELECTION_MODE_SINGLE: - if (oldMode == SELECTION_MODE_MULTIPLE || oldMode == SELECTION_MODE_RANGE) { - //We should only have one selection now, so we should pick one - List dates = getSelectedDates(); - if (!dates.isEmpty()) { - setSelectedDate(getSelectedDate()); - } - } - break; - default: - case SELECTION_MODE_NONE: - this.selectionMode = SELECTION_MODE_NONE; - if (oldMode != SELECTION_MODE_NONE) { - //No selection! Clear out! - clearSelection(); - } - break; - } - - adapter.setSelectionEnabled(selectionMode != SELECTION_MODE_NONE); - } - - /** - * Go to previous month or week without using the button {@link #buttonPast}. Should only go to - * previous if {@link #canGoBack()} is true, meaning it's possible to go to the previous month - * or week. - */ - public void goToPrevious() { - if (canGoBack()) { - pager.setCurrentItem(pager.getCurrentItem() - 1, true); + }; + + private CalendarDay minDate = null; + private CalendarDay maxDate = null; + + private OnDateSelectedListener listener; + private OnDateLongClickListener longClickListener; + private OnMonthChangedListener monthListener; + private OnRangeSelectedListener rangeListener; + + CharSequence calendarContentDescription; + private int accentColor = 0; + private int arrowColor = Color.BLACK; + private Drawable leftArrowMask; + private Drawable rightArrowMask; + private int tileHeight = INVALID_TILE_DIMENSION; + private int tileWidth = INVALID_TILE_DIMENSION; + @SelectionMode + private int selectionMode = SELECTION_MODE_SINGLE; + private boolean allowClickDaysOutsideCurrentMonth = true; + private DayOfWeek firstDayOfWeek; + private boolean showWeekDays; + + private State state; + + public MaterialCalendarView(Context context) { + this(context, null); + } + + public MaterialCalendarView(Context context, AttributeSet attrs) { + super(context, attrs); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + //If we're on good Android versions, turn off clipping for cool effects + setClipToPadding(false); + setClipChildren(false); + } else { + //Old Android does not like _not_ clipping view pagers, we need to clip + setClipChildren(true); + setClipToPadding(true); + } + + buttonPast = new DirectionButton(getContext()); + buttonPast.setContentDescription(getContext().getString(R.string.previous)); + title = new AppCompatTextView(getContext()); + buttonFuture = new DirectionButton(getContext()); + buttonFuture.setContentDescription(getContext().getString(R.string.next)); + pager = new CalendarPager(getContext()); + + buttonPast.setOnClickListener(onClickListener); + buttonFuture.setOnClickListener(onClickListener); + + titleChanger = new TitleChanger(title); + + pager.setOnPageChangeListener(pageChangeListener); + pager.setPageTransformer(false, new ViewPager.PageTransformer() { + @Override + public void transformPage(View page, float position) { + position = (float) Math.sqrt(1 - Math.abs(position)); + page.setAlpha(position); + } + }); + + TypedArray a = context.getTheme() + .obtainStyledAttributes(attrs, R.styleable.MaterialCalendarView, 0, 0); + try { + int calendarModeIndex = a.getInteger( + R.styleable.MaterialCalendarView_mcv_calendarMode, + 0 + ); + int firstDayOfWeekInt = a.getInteger( + R.styleable.MaterialCalendarView_mcv_firstDayOfWeek, + -1 + ); + + titleChanger.setOrientation( + a.getInteger( + R.styleable.MaterialCalendarView_mcv_titleAnimationOrientation, + VERTICAL + )); + + if (firstDayOfWeekInt >= 1 && firstDayOfWeekInt <= 7) { + firstDayOfWeek = DayOfWeek.of(firstDayOfWeekInt); + } else { + firstDayOfWeek = WeekFields.of(Locale.getDefault()).getFirstDayOfWeek(); + } + + showWeekDays = a.getBoolean(R.styleable.MaterialCalendarView_mcv_showWeekDays, true); + + newState() + .setFirstDayOfWeek(firstDayOfWeek) + .setCalendarDisplayMode(CalendarMode.values()[calendarModeIndex]) + .setShowWeekDays(showWeekDays) + .commit(); + + setSelectionMode(a.getInteger( + R.styleable.MaterialCalendarView_mcv_selectionMode, + SELECTION_MODE_SINGLE + )); + + final int tileSize = a.getLayoutDimension( + R.styleable.MaterialCalendarView_mcv_tileSize, + INVALID_TILE_DIMENSION + ); + if (tileSize > INVALID_TILE_DIMENSION) { + setTileSize(tileSize); + } + + final int tileWidth = a.getLayoutDimension( + R.styleable.MaterialCalendarView_mcv_tileWidth, + INVALID_TILE_DIMENSION + ); + if (tileWidth > INVALID_TILE_DIMENSION) { + setTileWidth(tileWidth); + } + + final int tileHeight = a.getLayoutDimension( + R.styleable.MaterialCalendarView_mcv_tileHeight, + INVALID_TILE_DIMENSION + ); + if (tileHeight > INVALID_TILE_DIMENSION) { + setTileHeight(tileHeight); + } + + setArrowColor(a.getColor( + R.styleable.MaterialCalendarView_mcv_arrowColor, + Color.BLACK + )); + Drawable leftMask = a.getDrawable( + R.styleable.MaterialCalendarView_mcv_leftArrowMask + ); + if (leftMask == null) { + leftMask = getResources().getDrawable(R.drawable.mcv_action_previous); + } + setLeftArrowMask(leftMask); + Drawable rightMask = a.getDrawable( + R.styleable.MaterialCalendarView_mcv_rightArrowMask + ); + if (rightMask == null) { + rightMask = getResources().getDrawable(R.drawable.mcv_action_next); + } + setRightArrowMask(rightMask); + + setSelectionColor( + a.getColor( + R.styleable.MaterialCalendarView_mcv_selectionColor, + getThemeAccentColor(context) + ) + ); + + CharSequence[] array = a.getTextArray(R.styleable.MaterialCalendarView_mcv_weekDayLabels); + if (array != null) { + setWeekDayFormatter(new ArrayWeekDayFormatter(array)); + } + + array = a.getTextArray(R.styleable.MaterialCalendarView_mcv_monthLabels); + if (array != null) { + setTitleFormatter(new MonthArrayTitleFormatter(array)); + } + + setHeaderTextAppearance(a.getResourceId( + R.styleable.MaterialCalendarView_mcv_headerTextAppearance, + R.style.TextAppearance_MaterialCalendarWidget_Header + )); + setWeekDayTextAppearance(a.getResourceId( + R.styleable.MaterialCalendarView_mcv_weekDayTextAppearance, + R.style.TextAppearance_MaterialCalendarWidget_WeekDay + )); + setDateTextAppearance(a.getResourceId( + R.styleable.MaterialCalendarView_mcv_dateTextAppearance, + R.style.TextAppearance_MaterialCalendarWidget_Date + )); + //noinspection ResourceType + setShowOtherDates(a.getInteger( + R.styleable.MaterialCalendarView_mcv_showOtherDates, + SHOW_DEFAULTS + )); + + setAllowClickDaysOutsideCurrentMonth(a.getBoolean( + R.styleable.MaterialCalendarView_mcv_allowClickDaysOutsideCurrentMonth, + true + )); + } catch (Exception e) { + e.printStackTrace(); + } finally { + a.recycle(); + } + + // Adapter is created while parsing the TypedArray attrs, so setup has to happen after + setupChildren(); + + currentMonth = CalendarDay.today(); + setCurrentDate(currentMonth); + + if (isInEditMode()) { + removeView(pager); + MonthView monthView = new MonthView(this, currentMonth, getFirstDayOfWeek(), true); + monthView.setSelectionColor(getSelectionColor()); + monthView.setDateTextAppearance(adapter.getDateTextAppearance()); + monthView.setWeekDayTextAppearance(adapter.getWeekDayTextAppearance()); + monthView.setShowOtherDates(getShowOtherDates()); + addView(monthView, new LayoutParams(calendarMode.visibleWeeksCount + DAY_NAMES_ROW)); + } + } + + private void setupChildren() { + topbar = new LinearLayout(getContext()); + topbar.setOrientation(LinearLayout.HORIZONTAL); + topbar.setClipChildren(false); + topbar.setClipToPadding(false); + addView(topbar, new LayoutParams(1)); + + buttonPast.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + topbar.addView(buttonPast, new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1)); + + title.setGravity(Gravity.CENTER); + topbar.addView(title, new LinearLayout.LayoutParams( + 0, LayoutParams.MATCH_PARENT, DEFAULT_DAYS_IN_WEEK - 2 + )); + + buttonFuture.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + topbar.addView(buttonFuture, new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1)); + + pager.setId(R.id.mcv_pager); + pager.setOffscreenPageLimit(1); + int tileHeight = showWeekDays ? calendarMode.visibleWeeksCount + DAY_NAMES_ROW + : calendarMode.visibleWeeksCount; + addView(pager, new LayoutParams(tileHeight)); + } + + private void updateUi() { + titleChanger.change(currentMonth); + buttonPast.setEnabled(canGoBack()); + buttonFuture.setEnabled(canGoForward()); + } + + /** + * Change the selection mode of the calendar. The default mode is {@linkplain #SELECTION_MODE_SINGLE} + * + * @param mode the selection mode to change to. This must be one of + * {@linkplain #SELECTION_MODE_NONE}, {@linkplain #SELECTION_MODE_SINGLE}, + * {@linkplain #SELECTION_MODE_RANGE} or {@linkplain #SELECTION_MODE_MULTIPLE}. + * Unknown values will act as {@linkplain #SELECTION_MODE_SINGLE} + * @see #getSelectionMode() + * @see #SELECTION_MODE_NONE + * @see #SELECTION_MODE_SINGLE + * @see #SELECTION_MODE_MULTIPLE + * @see #SELECTION_MODE_RANGE + */ + public void setSelectionMode(final @SelectionMode int mode) { + final @SelectionMode int oldMode = this.selectionMode; + this.selectionMode = mode; + switch (mode) { + case SELECTION_MODE_RANGE: + clearSelection(); + break; + case SELECTION_MODE_MULTIPLE: + break; + case SELECTION_MODE_SINGLE: + if (oldMode == SELECTION_MODE_MULTIPLE || oldMode == SELECTION_MODE_RANGE) { + //We should only have one selection now, so we should pick one + List dates = getSelectedDates(); + if (!dates.isEmpty()) { + setSelectedDate(getSelectedDate()); + } } - } - - /** - * Go to next month or week without using the button {@link #buttonFuture}. Should only go to - * next if {@link #canGoForward()} is enabled, meaning it's possible to go to the next month or - * week. - */ - public void goToNext() { - if (canGoForward()) { - pager.setCurrentItem(pager.getCurrentItem() + 1, true); + break; + default: + case SELECTION_MODE_NONE: + this.selectionMode = SELECTION_MODE_NONE; + if (oldMode != SELECTION_MODE_NONE) { + //No selection! Clear out! + clearSelection(); } + break; + } + + adapter.setSelectionEnabled(selectionMode != SELECTION_MODE_NONE); + } + + /** + * Go to previous month or week without using the button {@link #buttonPast}. Should only go to + * previous if {@link #canGoBack()} is true, meaning it's possible to go to the previous month + * or week. + */ + public void goToPrevious() { + if (canGoBack()) { + pager.setCurrentItem(pager.getCurrentItem() - 1, true); + } + } + + /** + * Go to next month or week without using the button {@link #buttonFuture}. Should only go to + * next if {@link #canGoForward()} is enabled, meaning it's possible to go to the next month or + * week. + */ + public void goToNext() { + if (canGoForward()) { + pager.setCurrentItem(pager.getCurrentItem() + 1, true); + } + } + + /** + * Get the current selection mode. The default mode is {@linkplain #SELECTION_MODE_SINGLE} + * + * @return the current selection mode + * @see #setSelectionMode(int) + * @see #SELECTION_MODE_NONE + * @see #SELECTION_MODE_SINGLE + * @see #SELECTION_MODE_MULTIPLE + * @see #SELECTION_MODE_RANGE + */ + @SelectionMode + public int getSelectionMode() { + return selectionMode; + } + + /** + * Use {@link #getTileWidth()} or {@link #getTileHeight()} instead. This method is deprecated + * and will just return the largest of the two sizes. + * + * @return tile height or width, whichever is larger + */ + @Deprecated + public int getTileSize() { + return Math.max(tileHeight, tileWidth); + } + + /** + * Set the size of each tile that makes up the calendar. + * Each day is 1 tile, so the widget is 7 tiles wide and 7 or 8 tiles tall + * depending on the visibility of the {@link #topbar}. + * + * @param size the new size for each tile in pixels + */ + public void setTileSize(int size) { + this.tileWidth = size; + this.tileHeight = size; + requestLayout(); + } + + /** + * @param tileSizeDp the new size for each tile in dips + * @see #setTileSize(int) + */ + public void setTileSizeDp(int tileSizeDp) { + setTileSize(dpToPx(tileSizeDp)); + } + + /** + * @return the height of tiles in pixels + */ + public int getTileHeight() { + return tileHeight; + } + + /** + * Set the height of each tile that makes up the calendar. + * + * @param height the new height for each tile in pixels + */ + public void setTileHeight(int height) { + this.tileHeight = height; + requestLayout(); + } + + /** + * @param tileHeightDp the new height for each tile in dips + * @see #setTileHeight(int) + */ + public void setTileHeightDp(int tileHeightDp) { + setTileHeight(dpToPx(tileHeightDp)); + } + + /** + * @return the width of tiles in pixels + */ + public int getTileWidth() { + return tileWidth; + } + + /** + * Set the width of each tile that makes up the calendar. + * + * @param width the new width for each tile in pixels + */ + public void setTileWidth(int width) { + this.tileWidth = width; + requestLayout(); + } + + /** + * @param tileWidthDp the new width for each tile in dips + * @see #setTileWidth(int) + */ + public void setTileWidthDp(int tileWidthDp) { + setTileWidth(dpToPx(tileWidthDp)); + } + + private int dpToPx(int dp) { + return (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics() + ); + } + + /** + * Whether the pager can page forward, meaning the future month is enabled. + * + * @return true if there is a future month that can be shown + */ + public boolean canGoForward() { + return pager.getCurrentItem() < (adapter.getCount() - 1); + } + + /** + * Whether the pager can page backward, meaning the previous month is enabled. + * + * @return true if there is a previous month that can be shown + */ + public boolean canGoBack() { + return pager.getCurrentItem() > 0; + } + + /** + * Pass all touch events to the pager so scrolling works on the edges of the calendar view. + */ + @Override + public boolean onTouchEvent(MotionEvent event) { + return pager.dispatchTouchEvent(event); + } + + /** + * @return the color used for the selection + */ + public int getSelectionColor() { + return accentColor; + } + + /** + * @param color The selection color + */ + public void setSelectionColor(int color) { + if (color == 0) { + if (!isInEditMode()) { + return; + } else { + color = Color.GRAY; + } + } + accentColor = color; + adapter.setSelectionColor(color); + invalidate(); + } + + /** + * @return color used to draw arrows + */ + public int getArrowColor() { + return arrowColor; + } + + /** + * @param color the new color for the paging arrows + */ + public void setArrowColor(int color) { + if (color == 0) { + return; + } + arrowColor = color; + buttonPast.setColor(color); + buttonFuture.setColor(color); + invalidate(); + } + + /** + * Set content description for button past + * + * @param description String to use as content description + */ + public void setContentDescriptionArrowPast(final CharSequence description) { + buttonPast.setContentDescription(description); + } + + /** + * Set content description for button future + * + * @param description String to use as content description + */ + public void setContentDescriptionArrowFuture(final CharSequence description) { + buttonFuture.setContentDescription(description); + } + + /** + * Set content description for calendar + * + * @param description String to use as content description + */ + public void setContentDescriptionCalendar(final CharSequence description) { + calendarContentDescription = description; + } + + /** + * Get content description for calendar + * + * @return calendar's content description + */ + public CharSequence getCalendarContentDescription() { + return calendarContentDescription != null + ? calendarContentDescription + : getContext().getString(R.string.calendar); + } + + /** + * Set a formatter for day content description. + * + * @param formatter the new formatter, null for default + */ + public void setDayFormatterContentDescription(DayFormatter formatter) { + adapter.setDayFormatterContentDescription(formatter); + } + + /** + * @return icon used for the left arrow + */ + public Drawable getLeftArrowMask() { + return leftArrowMask; + } + + /** + * @param icon the new icon to use for the left paging arrow + */ + public void setLeftArrowMask(Drawable icon) { + leftArrowMask = icon; + buttonPast.setImageDrawable(icon); + } + + /** + * @return icon used for the right arrow + */ + public Drawable getRightArrowMask() { + return rightArrowMask; + } + + /** + * @param icon the new icon to use for the right paging arrow + */ + public void setRightArrowMask(Drawable icon) { + rightArrowMask = icon; + buttonFuture.setImageDrawable(icon); + } + + /** + * @param resourceId The text appearance resource id. + */ + public void setHeaderTextAppearance(int resourceId) { + title.setTextAppearance(getContext(), resourceId); + } + + /** + * @param resourceId The text appearance resource id. + */ + public void setDateTextAppearance(int resourceId) { + adapter.setDateTextAppearance(resourceId); + } + + /** + * @param resourceId The text appearance resource id. + */ + public void setWeekDayTextAppearance(int resourceId) { + adapter.setWeekDayTextAppearance(resourceId); + } + + /** + * Get the currently selected date, or null if no selection. Depending on the selection mode, + * you might get different results. + * + *

For {@link #SELECTION_MODE_SINGLE}, returns the selected date.

+ *

For {@link #SELECTION_MODE_MULTIPLE}, returns the last date selected.

+ *

For {@link #SELECTION_MODE_RANGE}, returns the last date of the range. In most cases, you should probably be using {@link #getSelectedDates()}.

+ *

For {@link #SELECTION_MODE_NONE}, returns null.

+ * + * @return The selected day, or null if no selection. If in multiple selection mode, this + * will return the last date of the list of selected dates. + * @see MaterialCalendarView#getSelectedDates() + */ + @Nullable public CalendarDay getSelectedDate() { + List dates = adapter.getSelectedDates(); + if (dates.isEmpty()) { + return null; + } else { + return dates.get(dates.size() - 1); + } + } + + /** + * Return the list of currently selected dates. Mostly useful for {@link #SELECTION_MODE_MULTIPLE} + * and {@link #SELECTION_MODE_RANGE}. For the other modes, check {@link #getSelectedDate()}. + * + *

For {@link #SELECTION_MODE_MULTIPLE}, returns the list in the order of selection.

+ *

For {@link #SELECTION_MODE_RANGE}, returns the range of dates ordered chronologically.

+ * + * @return All of the currently selected dates. + * @see MaterialCalendarView#getSelectedDate() + */ + @NonNull public List getSelectedDates() { + return adapter.getSelectedDates(); + } + + /** + * Clear the currently selected date(s) + */ + public void clearSelection() { + List dates = getSelectedDates(); + adapter.clearSelections(); + for (CalendarDay day : dates) { + dispatchOnDateSelected(day, false); + } + } + + /** + * @param date a Date set to a day to select. Null to clear selection + */ + public void setSelectedDate(@Nullable LocalDate date) { + setSelectedDate(CalendarDay.from(date)); + } + + /** + * @param date a Date to set as selected. Null to clear selection + */ + public void setSelectedDate(@Nullable CalendarDay date) { + clearSelection(); + if (date != null) { + setDateSelected(date, true); + } + } + + /** + * @param day a CalendarDay to change. Passing null does nothing + * @param selected true if day should be selected, false to deselect + */ + public void setDateSelected(@Nullable CalendarDay day, boolean selected) { + if (day == null) { + return; + } + adapter.setDateSelected(day, selected); + } + + /** + * Get the current first day of the month in month mode, or the first visible day of the + * currently visible week. + * + * For example, in week mode, if the week is July 29th, 2018 to August 4th, 2018, + * this will return July 29th, 2018. If in month mode and the month is august, then this method + * will return August 1st, 2018. + * + * @return The current month or week shown, will be set to first day of the month in month mode, + * or the first visible day for a week. + */ + public CalendarDay getCurrentDate() { + return adapter.getItem(pager.getCurrentItem()); + } + + /** + * Set the calendar to a specific month or week based on a date. + * + * In month mode, the calendar will be set to the corresponding month. + * + * In week mode, the calendar will be set to the corresponding week. + * + * @param calendar a Calendar set to a day to focus the calendar on. Null will do nothing + */ + public void setCurrentDate(@Nullable LocalDate calendar) { + setCurrentDate(CalendarDay.from(calendar)); + } + + /** + * Set the calendar to a specific month or week based on a date. + * + * In month mode, the calendar will be set to the corresponding month. + * + * In week mode, the calendar will be set to the corresponding week. + * + * @param day a CalendarDay to focus the calendar on. Null will do nothing + */ + public void setCurrentDate(@Nullable CalendarDay day) { + setCurrentDate(day, true); + } + + /** + * Set the calendar to a specific month or week based on a date. + * + * In month mode, the calendar will be set to the corresponding month. + * + * In week mode, the calendar will be set to the corresponding week. + * + * @param day a CalendarDay to focus the calendar on. Null will do nothing + * @param useSmoothScroll use smooth scroll when changing months. + */ + public void setCurrentDate(@Nullable CalendarDay day, boolean useSmoothScroll) { + if (day == null) { + return; + } + int index = adapter.getIndexForDay(day); + pager.setCurrentItem(index, useSmoothScroll); + updateUi(); + } + + /** + * @return the minimum selectable date for the calendar, if any + */ + public CalendarDay getMinimumDate() { + return minDate; + } + + /** + * @return the maximum selectable date for the calendar, if any + */ + public CalendarDay getMaximumDate() { + return maxDate; + } + + /** + * The default value is {@link #SHOW_DEFAULTS}, which currently is just {@link #SHOW_DECORATED_DISABLED}. + * This means that the default visible days are of the current month, in the min-max range. + * + * @param showOtherDates flags for showing non-enabled dates + * @see #SHOW_ALL + * @see #SHOW_NONE + * @see #SHOW_DEFAULTS + * @see #SHOW_OTHER_MONTHS + * @see #SHOW_OUT_OF_RANGE + * @see #SHOW_DECORATED_DISABLED + */ + public void setShowOtherDates(@ShowOtherDates int showOtherDates) { + adapter.setShowOtherDates(showOtherDates); + } + + /** + * Allow the user to click on dates from other months that are not out of range. Go to next or + * previous month if a day outside the current month is clicked. The day still need to be + * enabled to be selected. + * Default value is true. Should be used with {@link #SHOW_OTHER_MONTHS}. + * + * @param enabled True to allow the user to click on a day outside current month displayed + */ + public void setAllowClickDaysOutsideCurrentMonth(final boolean enabled) { + this.allowClickDaysOutsideCurrentMonth = enabled; + } + + /** + * Set a formatter for weekday labels. + * + * @param formatter the new formatter, null for default + */ + public void setWeekDayFormatter(WeekDayFormatter formatter) { + adapter.setWeekDayFormatter(formatter == null ? WeekDayFormatter.DEFAULT : formatter); + } + + /** + * Set a formatter for day labels. + * + * @param formatter the new formatter, null for default + */ + public void setDayFormatter(DayFormatter formatter) { + adapter.setDayFormatter(formatter == null ? DayFormatter.DEFAULT : formatter); + } + + /** + * Set a {@linkplain com.prolificinteractive.materialcalendarview.format.WeekDayFormatter} + * with the provided week day labels + * + * @param weekDayLabels Labels to use for the days of the week + * @see com.prolificinteractive.materialcalendarview.format.ArrayWeekDayFormatter + * @see #setWeekDayFormatter(com.prolificinteractive.materialcalendarview.format.WeekDayFormatter) + */ + public void setWeekDayLabels(CharSequence[] weekDayLabels) { + setWeekDayFormatter(new ArrayWeekDayFormatter(weekDayLabels)); + } + + /** + * Set a {@linkplain com.prolificinteractive.materialcalendarview.format.WeekDayFormatter} + * with the provided week day labels + * + * @param arrayRes String array resource of week day labels + * @see com.prolificinteractive.materialcalendarview.format.ArrayWeekDayFormatter + * @see #setWeekDayFormatter(com.prolificinteractive.materialcalendarview.format.WeekDayFormatter) + */ + public void setWeekDayLabels(@ArrayRes int arrayRes) { + setWeekDayLabels(getResources().getTextArray(arrayRes)); + } + + /** + * @return int of flags used for showing non-enabled dates + * @see #SHOW_ALL + * @see #SHOW_NONE + * @see #SHOW_DEFAULTS + * @see #SHOW_OTHER_MONTHS + * @see #SHOW_OUT_OF_RANGE + * @see #SHOW_DECORATED_DISABLED + */ + @ShowOtherDates + public int getShowOtherDates() { + return adapter.getShowOtherDates(); + } + + /** + * @return true if allow click on days outside current month displayed + */ + public boolean allowClickDaysOutsideCurrentMonth() { + return allowClickDaysOutsideCurrentMonth; + } + + /** + * @return true if the week days names are shown + */ + public boolean isShowWeekDays() { + return showWeekDays; + } + + /** + * Set a custom formatter for the month/year title + * + * @param titleFormatter new formatter to use, null to use default formatter + */ + public void setTitleFormatter(@Nullable TitleFormatter titleFormatter) { + titleChanger.setTitleFormatter(titleFormatter); + adapter.setTitleFormatter(titleFormatter); + updateUi(); + } + + /** + * Set a {@linkplain com.prolificinteractive.materialcalendarview.format.TitleFormatter} + * using the provided month labels + * + * @param monthLabels month labels to use + * @see com.prolificinteractive.materialcalendarview.format.MonthArrayTitleFormatter + * @see #setTitleFormatter(com.prolificinteractive.materialcalendarview.format.TitleFormatter) + */ + public void setTitleMonths(CharSequence[] monthLabels) { + setTitleFormatter(new MonthArrayTitleFormatter(monthLabels)); + } + + /** + * Set a {@linkplain com.prolificinteractive.materialcalendarview.format.TitleFormatter} + * using the provided month labels + * + * @param arrayRes String array resource of month labels to use + * @see com.prolificinteractive.materialcalendarview.format.MonthArrayTitleFormatter + * @see #setTitleFormatter(com.prolificinteractive.materialcalendarview.format.TitleFormatter) + */ + public void setTitleMonths(@ArrayRes int arrayRes) { + setTitleMonths(getResources().getTextArray(arrayRes)); + } + + /** + * Change the title animation orientation to have a different look and feel. + * + * @param orientation {@link MaterialCalendarView#VERTICAL} or {@link MaterialCalendarView#HORIZONTAL} + */ + public void setTitleAnimationOrientation(final int orientation) { + titleChanger.setOrientation(orientation); + } + + /** + * Get the orientation of the animation of the title. + * + * @return Title animation orientation {@link MaterialCalendarView#VERTICAL} or {@link MaterialCalendarView#HORIZONTAL} + */ + public int getTitleAnimationOrientation() { + return titleChanger.getOrientation(); + } + + /** + * Sets the visibility {@link #topbar}, which contains + * the previous month button {@link #buttonPast}, next month button {@link #buttonFuture}, + * and the month title {@link #title}. + * + * @param visible Boolean indicating if the topbar is visible + */ + public void setTopbarVisible(boolean visible) { + topbar.setVisibility(visible ? View.VISIBLE : View.GONE); + requestLayout(); + } + + /** + * @return true if the topbar is visible + */ + public boolean getTopbarVisible() { + return topbar.getVisibility() == View.VISIBLE; + } + + /** + * Get the current {@link CalendarMode} set of the Calendar. + * + * @return Whichever mode the calendar is currently in. + */ + public CalendarMode getCalendarMode() { + return calendarMode; + } + + @Override + protected Parcelable onSaveInstanceState() { + SavedState ss = new SavedState(super.onSaveInstanceState()); + ss.color = getSelectionColor(); + ss.dateTextAppearance = adapter.getDateTextAppearance(); + ss.weekDayTextAppearance = adapter.getWeekDayTextAppearance(); + ss.showOtherDates = getShowOtherDates(); + ss.allowClickDaysOutsideCurrentMonth = allowClickDaysOutsideCurrentMonth(); + ss.minDate = getMinimumDate(); + ss.maxDate = getMaximumDate(); + ss.selectedDates = getSelectedDates(); + ss.firstDayOfWeek = getFirstDayOfWeek(); + ss.orientation = getTitleAnimationOrientation(); + ss.selectionMode = getSelectionMode(); + ss.tileWidthPx = getTileWidth(); + ss.tileHeightPx = getTileHeight(); + ss.topbarVisible = getTopbarVisible(); + ss.calendarMode = calendarMode; + ss.dynamicHeightEnabled = mDynamicHeightEnabled; + ss.currentMonth = currentMonth; + ss.cacheCurrentPosition = state.cacheCurrentPosition; + ss.showWeekDays = showWeekDays; + return ss; + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + SavedState ss = (SavedState) state; + super.onRestoreInstanceState(ss.getSuperState()); + newState() + .setFirstDayOfWeek(ss.firstDayOfWeek) + .setCalendarDisplayMode(ss.calendarMode) + .setMinimumDate(ss.minDate) + .setMaximumDate(ss.maxDate) + .isCacheCalendarPositionEnabled(ss.cacheCurrentPosition) + .setShowWeekDays(ss.showWeekDays) + .commit(); + + setSelectionColor(ss.color); + setDateTextAppearance(ss.dateTextAppearance); + setWeekDayTextAppearance(ss.weekDayTextAppearance); + setShowOtherDates(ss.showOtherDates); + setAllowClickDaysOutsideCurrentMonth(ss.allowClickDaysOutsideCurrentMonth); + clearSelection(); + for (CalendarDay calendarDay : ss.selectedDates) { + setDateSelected(calendarDay, true); + } + setTitleAnimationOrientation(ss.orientation); + setTileWidth(ss.tileWidthPx); + setTileHeight(ss.tileHeightPx); + setTopbarVisible(ss.topbarVisible); + setSelectionMode(ss.selectionMode); + setDynamicHeightEnabled(ss.dynamicHeightEnabled); + setCurrentDate(ss.currentMonth); + } + + @Override + protected void dispatchSaveInstanceState(@NonNull SparseArray container) { + dispatchFreezeSelfOnly(container); + } + + @Override + protected void dispatchRestoreInstanceState(@NonNull SparseArray container) { + dispatchThawSelfOnly(container); + } + + private void setRangeDates(CalendarDay min, CalendarDay max) { + CalendarDay c = currentMonth; + adapter.setRangeDates(min, max); + currentMonth = c; + if (min != null) { + currentMonth = min.isAfter(currentMonth) ? min : currentMonth; + } + int position = adapter.getIndexForDay(c); + pager.setCurrentItem(position, false); + updateUi(); + } + + public static class SavedState extends BaseSavedState { + + int color = 0; + int dateTextAppearance = 0; + int weekDayTextAppearance = 0; + int showOtherDates = SHOW_DEFAULTS; + boolean allowClickDaysOutsideCurrentMonth = true; + CalendarDay minDate = null; + CalendarDay maxDate = null; + List selectedDates = new ArrayList<>(); + DayOfWeek firstDayOfWeek = WeekFields.of(Locale.getDefault()).getFirstDayOfWeek(); + int orientation = 0; + int tileWidthPx = -1; + int tileHeightPx = -1; + boolean topbarVisible = true; + int selectionMode = SELECTION_MODE_SINGLE; + boolean dynamicHeightEnabled = false; + CalendarMode calendarMode = CalendarMode.MONTHS; + CalendarDay currentMonth = null; + boolean cacheCurrentPosition; + boolean showWeekDays; + + SavedState(Parcelable superState) { + super(superState); } - /** - * Get the current selection mode. The default mode is {@linkplain #SELECTION_MODE_SINGLE} - * - * @return the current selection mode - * @see #setSelectionMode(int) - * @see #SELECTION_MODE_NONE - * @see #SELECTION_MODE_SINGLE - * @see #SELECTION_MODE_MULTIPLE - * @see #SELECTION_MODE_RANGE - */ - @SelectionMode - public int getSelectionMode() { - return selectionMode; - } - - /** - * Use {@link #getTileWidth()} or {@link #getTileHeight()} instead. This method is deprecated - * and will just return the largest of the two sizes. - * - * @return tile height or width, whichever is larger - */ - @Deprecated - public int getTileSize() { - return Math.max(tileHeight, tileWidth); - } - - /** - * Set the size of each tile that makes up the calendar. - * Each day is 1 tile, so the widget is 7 tiles wide and 7 or 8 tiles tall - * depending on the visibility of the {@link #topbar}. - * - * @param size the new size for each tile in pixels - */ - public void setTileSize(int size) { - this.tileWidth = size; - this.tileHeight = size; - requestLayout(); - } - - /** - * @param tileSizeDp the new size for each tile in dips - * @see #setTileSize(int) - */ - public void setTileSizeDp(int tileSizeDp) { - setTileSize(dpToPx(tileSizeDp)); - } - - /** - * @return the height of tiles in pixels - */ - public int getTileHeight() { - return tileHeight; - } - - /** - * Set the height of each tile that makes up the calendar. - * - * @param height the new height for each tile in pixels - */ - public void setTileHeight(int height) { - this.tileHeight = height; - requestLayout(); - } - - /** - * @param tileHeightDp the new height for each tile in dips - * @see #setTileHeight(int) - */ - public void setTileHeightDp(int tileHeightDp) { - setTileHeight(dpToPx(tileHeightDp)); - } - - /** - * @return the width of tiles in pixels - */ - public int getTileWidth() { - return tileWidth; - } - - /** - * Set the width of each tile that makes up the calendar. - * - * @param width the new width for each tile in pixels - */ - public void setTileWidth(int width) { - this.tileWidth = width; - requestLayout(); - } - - /** - * @param tileWidthDp the new width for each tile in dips - * @see #setTileWidth(int) - */ - public void setTileWidthDp(int tileWidthDp) { - setTileWidth(dpToPx(tileWidthDp)); - } - - private int dpToPx(int dp) { - return (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics() - ); - } - - /** - * Whether the pager can page forward, meaning the future month is enabled. - * - * @return true if there is a future month that can be shown - */ - public boolean canGoForward() { - return pager.getCurrentItem() < (adapter.getCount() - 1); - } - - /** - * Whether the pager can page backward, meaning the previous month is enabled. - * - * @return true if there is a previous month that can be shown - */ - public boolean canGoBack() { - return pager.getCurrentItem() > 0; - } - - /** - * Pass all touch events to the pager so scrolling works on the edges of the calendar view. - * - * @param event - * @return - */ @Override - public boolean onTouchEvent(MotionEvent event) { - return pager.dispatchTouchEvent(event); - } - - /** - * @return the color used for the selection - */ - public int getSelectionColor() { - return accentColor; - } - - /** - * @param color The selection color - */ - public void setSelectionColor(int color) { - if (color == 0) { - if (!isInEditMode()) { - return; - } else { - color = Color.GRAY; - } - } - accentColor = color; - adapter.setSelectionColor(color); - invalidate(); - } - - /** - * @return color used to draw arrows - */ - public int getArrowColor() { - return arrowColor; - } + public void writeToParcel(@NonNull Parcel out, int flags) { + super.writeToParcel(out, flags); + out.writeInt(color); + out.writeInt(dateTextAppearance); + out.writeInt(weekDayTextAppearance); + out.writeInt(showOtherDates); + out.writeByte((byte) (allowClickDaysOutsideCurrentMonth ? 1 : 0)); + out.writeParcelable(minDate, 0); + out.writeParcelable(maxDate, 0); + out.writeTypedList(selectedDates); + out.writeInt(firstDayOfWeek.getValue()); + out.writeInt(orientation); + out.writeInt(tileWidthPx); + out.writeInt(tileHeightPx); + out.writeInt(topbarVisible ? 1 : 0); + out.writeInt(selectionMode); + out.writeInt(dynamicHeightEnabled ? 1 : 0); + out.writeInt(calendarMode == CalendarMode.WEEKS ? 1 : 0); + out.writeParcelable(currentMonth, 0); + out.writeByte((byte) (cacheCurrentPosition ? 1 : 0)); + out.writeByte((byte) (showWeekDays ? 1 : 0)); + } + + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; - /** - * @param color the new color for the paging arrows - */ - public void setArrowColor(int color) { - if (color == 0) { - return; + private SavedState(Parcel in) { + super(in); + color = in.readInt(); + dateTextAppearance = in.readInt(); + weekDayTextAppearance = in.readInt(); + showOtherDates = in.readInt(); + allowClickDaysOutsideCurrentMonth = in.readByte() != 0; + ClassLoader loader = CalendarDay.class.getClassLoader(); + minDate = in.readParcelable(loader); + maxDate = in.readParcelable(loader); + in.readTypedList(selectedDates, CalendarDay.CREATOR); + firstDayOfWeek = DayOfWeek.of(in.readInt()); + orientation = in.readInt(); + tileWidthPx = in.readInt(); + tileHeightPx = in.readInt(); + topbarVisible = in.readInt() == 1; + selectionMode = in.readInt(); + dynamicHeightEnabled = in.readInt() == 1; + calendarMode = in.readInt() == 1 ? CalendarMode.WEEKS : CalendarMode.MONTHS; + currentMonth = in.readParcelable(loader); + cacheCurrentPosition = in.readByte() != 0; + showWeekDays = in.readByte() != 0; + } + } + + private static int getThemeAccentColor(Context context) { + int colorAttr; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + colorAttr = android.R.attr.colorAccent; + } else { + //Get colorAccent defined for AppCompat + colorAttr = + context.getResources().getIdentifier("colorAccent", "attr", context.getPackageName()); + } + TypedValue outValue = new TypedValue(); + context.getTheme().resolveAttribute(colorAttr, outValue, true); + return outValue.data; + } + + /** + * @return The first day of the week as a {@linkplain Calendar} day constant. + */ + public DayOfWeek getFirstDayOfWeek() { + return firstDayOfWeek; + } + + /** + * By default, the calendar will take up all the space needed to show any month (6 rows). + * By enabling dynamic height, the view will change height dependant on the visible month. + *

+ * This means months that only need 5 or 4 rows to show the entire month will only take up + * that many rows, and will grow and shrink as necessary. + * + * @param useDynamicHeight true to have the view different heights based on the visible month + */ + public void setDynamicHeightEnabled(boolean useDynamicHeight) { + this.mDynamicHeightEnabled = useDynamicHeight; + } + + /** + * @return the dynamic height state - true if enabled. + */ + public boolean isDynamicHeightEnabled() { + return mDynamicHeightEnabled; + } + + /** + * Add a collection of day decorators + * + * @param decorators decorators to add + */ + public void addDecorators(Collection decorators) { + if (decorators == null) { + return; + } + + dayViewDecorators.addAll(decorators); + adapter.setDecorators(dayViewDecorators); + } + + /** + * Add several day decorators + * + * @param decorators decorators to add + */ + public void addDecorators(DayViewDecorator... decorators) { + addDecorators(Arrays.asList(decorators)); + } + + /** + * Add a day decorator + * + * @param decorator decorator to add + */ + public void addDecorator(DayViewDecorator decorator) { + if (decorator == null) { + return; + } + dayViewDecorators.add(decorator); + adapter.setDecorators(dayViewDecorators); + } + + /** + * Remove all decorators + */ + public void removeDecorators() { + dayViewDecorators.clear(); + adapter.setDecorators(dayViewDecorators); + } + + /** + * Remove a specific decorator instance. Same rules as {@linkplain List#remove(Object)} + * + * @param decorator decorator to remove + */ + public void removeDecorator(DayViewDecorator decorator) { + dayViewDecorators.remove(decorator); + adapter.setDecorators(dayViewDecorators); + } + + /** + * Invalidate decorators after one has changed internally. That is, if a decorator mutates, you + * should call this method to update the widget. + */ + public void invalidateDecorators() { + adapter.invalidateDecorators(); + } + + /* + * Listener/Callback Code + */ + + /** + * Sets the listener to be notified upon selected date changes. + * + * @param listener thing to be notified + */ + public void setOnDateChangedListener(OnDateSelectedListener listener) { + this.listener = listener; + } + + /** + * Sets the listener to be notified upon long clicks on dates. + * + * @param longClickListener thing to be notified + */ + public void setOnDateLongClickListener(OnDateLongClickListener longClickListener) { + this.longClickListener = longClickListener; + } + + /** + * Sets the listener to be notified upon month changes. + * + * @param listener thing to be notified + */ + public void setOnMonthChangedListener(OnMonthChangedListener listener) { + this.monthListener = listener; + } + + /** + * Sets the listener to be notified upon a range has been selected. + * + * @param listener thing to be notified + */ + public void setOnRangeSelectedListener(OnRangeSelectedListener listener) { + this.rangeListener = listener; + } + + /** + * Add listener to the title or null to remove it. + * + * @param listener Listener to be notified. + */ + public void setOnTitleClickListener(final OnClickListener listener) { + title.setOnClickListener(listener); + } + + /** + * Dispatch date change events to a listener, if set + * + * @param day the day that was selected + * @param selected true if the day is now currently selected, false otherwise + */ + protected void dispatchOnDateSelected(final CalendarDay day, final boolean selected) { + if (listener != null) { + listener.onDateSelected(MaterialCalendarView.this, day, selected); + } + } + + /** + * Dispatch a range of days to a range listener, if set, ordered chronologically. + * + * @param days Enclosing days ordered from first to last day. + */ + protected void dispatchOnRangeSelected(@NonNull final List days) { + if (rangeListener != null) { + rangeListener.onRangeSelected(MaterialCalendarView.this, days); + } + } + + /** + * Dispatch date change events to a listener, if set + * + * @param day first day of the new month + */ + protected void dispatchOnMonthChanged(final CalendarDay day) { + if (monthListener != null) { + monthListener.onMonthChanged(MaterialCalendarView.this, day); + } + } + + /** + * Call by {@link CalendarPagerView} to indicate that a day was clicked and we should handle it. + * This method will always process the click to the selected date. + * + * @param date date of the day that was clicked + * @param nowSelected true if the date is now selected, false otherwise + */ + protected void onDateClicked(@NonNull CalendarDay date, boolean nowSelected) { + switch (selectionMode) { + case SELECTION_MODE_MULTIPLE: { + adapter.setDateSelected(date, nowSelected); + dispatchOnDateSelected(date, nowSelected); + } + break; + case SELECTION_MODE_RANGE: { + final List currentSelection = adapter.getSelectedDates(); + + if (currentSelection.size() == 0) { + // Selecting the first date of a range + adapter.setDateSelected(date, nowSelected); + dispatchOnDateSelected(date, nowSelected); + } else if (currentSelection.size() == 1) { + // Selecting the second date of a range + final CalendarDay firstDaySelected = currentSelection.get(0); + if (firstDaySelected.equals(date)) { + // Right now, we are not supporting a range of one day, so we are removing the day instead. + adapter.setDateSelected(date, nowSelected); + dispatchOnDateSelected(date, nowSelected); + } else if (firstDaySelected.isAfter(date)) { + // Selecting a range, dispatching in reverse order... + adapter.selectRange(date, firstDaySelected); + dispatchOnRangeSelected(adapter.getSelectedDates()); + } else { + // Selecting a range, dispatching in order... + adapter.selectRange(firstDaySelected, date); + dispatchOnRangeSelected(adapter.getSelectedDates()); + } + } else { + // Clearing selection and making a selection of the new date. + adapter.clearSelections(); + adapter.setDateSelected(date, nowSelected); + dispatchOnDateSelected(date, nowSelected); } - arrowColor = color; - buttonPast.setColor(color); - buttonFuture.setColor(color); - invalidate(); - } - - /** - * Set content description for button past - * - * @param description String to use as content description - */ - public void setContentDescriptionArrowPast(final CharSequence description) { - buttonPast.setContentDescription(description); - } + } + break; + default: + case SELECTION_MODE_SINGLE: { + adapter.clearSelections(); + adapter.setDateSelected(date, true); + dispatchOnDateSelected(date, true); + } + break; + } + } + + /** + * Select a fresh range of date including first day and last day. + * + * @param firstDay first day of the range to select + * @param lastDay last day of the range to select + */ + public void selectRange(final CalendarDay firstDay, final CalendarDay lastDay) { + if (firstDay == null || lastDay == null) { + return; + } else if (firstDay.isAfter(lastDay)) { + adapter.selectRange(lastDay, firstDay); + dispatchOnRangeSelected(adapter.getSelectedDates()); + } else { + adapter.selectRange(firstDay, lastDay); + dispatchOnRangeSelected(adapter.getSelectedDates()); + } + } + + /** + * Call by {@link CalendarPagerView} to indicate that a day was clicked and we should handle it + */ + protected void onDateClicked(final DayView dayView) { + final CalendarDay currentDate = getCurrentDate(); + final CalendarDay selectedDate = dayView.getDate(); + final int currentMonth = currentDate.getMonth(); + final int selectedMonth = selectedDate.getMonth(); + + if (calendarMode == CalendarMode.MONTHS + && allowClickDaysOutsideCurrentMonth + && currentMonth != selectedMonth) { + if (currentDate.isAfter(selectedDate)) { + goToPrevious(); + } else if (currentDate.isBefore(selectedDate)) { + goToNext(); + } + } + onDateClicked(dayView.getDate(), !dayView.isChecked()); + } + + /** + * Call by {@link CalendarPagerView} to indicate that a day was long clicked and we should handle it + */ + protected void onDateLongClicked(final DayView dayView) { + if (longClickListener != null) { + longClickListener.onDateLongClick(MaterialCalendarView.this, dayView.getDate()); + } + } + + /** + * Called by the adapter for cases when changes in state result in dates being unselected + * + * @param date date that should be de-selected + */ + protected void onDateUnselected(CalendarDay date) { + dispatchOnDateSelected(date, false); + } + + /* + * Show Other Dates Utils + */ + + /** + * @param showOtherDates int flag for show other dates + * @return true if the other months flag is set + */ + public static boolean showOtherMonths(@ShowOtherDates int showOtherDates) { + return (showOtherDates & SHOW_OTHER_MONTHS) != 0; + } + + /** + * @param showOtherDates int flag for show other dates + * @return true if the out of range flag is set + */ + public static boolean showOutOfRange(@ShowOtherDates int showOtherDates) { + return (showOtherDates & SHOW_OUT_OF_RANGE) != 0; + } + + /** + * @param showOtherDates int flag for show other dates + * @return true if the decorated disabled flag is set + */ + public static boolean showDecoratedDisabled(@ShowOtherDates int showOtherDates) { + return (showOtherDates & SHOW_DECORATED_DISABLED) != 0; + } + + /* + * Custom ViewGroup Code + */ + + /** + * {@inheritDoc} + */ + @Override + protected LayoutParams generateDefaultLayoutParams() { + return new LayoutParams(1); + } + + /** + * {@inheritDoc} + */ + @Override + protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { + final int specWidthSize = MeasureSpec.getSize(widthMeasureSpec); + final int specWidthMode = MeasureSpec.getMode(widthMeasureSpec); + final int specHeightSize = MeasureSpec.getSize(heightMeasureSpec); + final int specHeightMode = MeasureSpec.getMode(heightMeasureSpec); + + //We need to disregard padding for a while. This will be added back later + final int desiredWidth = specWidthSize - getPaddingLeft() - getPaddingRight(); + final int desiredHeight = specHeightSize - getPaddingTop() - getPaddingBottom(); + + final int weekCount = getWeekCountBasedOnMode(); + + final int viewTileHeight = getTopbarVisible() ? (weekCount + 1) : weekCount; + + //Calculate independent tile sizes for later + int desiredTileWidth = desiredWidth / DEFAULT_DAYS_IN_WEEK; + int desiredTileHeight = desiredHeight / viewTileHeight; + + int measureTileSize = -1; + int measureTileWidth = -1; + int measureTileHeight = -1; + + if (this.tileWidth != INVALID_TILE_DIMENSION || this.tileHeight != INVALID_TILE_DIMENSION) { + if (this.tileWidth > 0) { + //We have a tileWidth set, we should use that + measureTileWidth = this.tileWidth; + } else { + measureTileWidth = desiredTileWidth; + } + if (this.tileHeight > 0) { + //We have a tileHeight set, we should use that + measureTileHeight = this.tileHeight; + } else { + measureTileHeight = desiredTileHeight; + } + } else if (specWidthMode == MeasureSpec.EXACTLY || specWidthMode == MeasureSpec.AT_MOST) { + if (specHeightMode == MeasureSpec.EXACTLY) { + //Pick the smaller of the two explicit sizes + measureTileSize = Math.min(desiredTileWidth, desiredTileHeight); + } else { + //Be the width size the user wants + measureTileSize = desiredTileWidth; + } + } else if (specHeightMode == MeasureSpec.EXACTLY || specHeightMode == MeasureSpec.AT_MOST) { + //Be the height size the user wants + measureTileSize = desiredTileHeight; + } + + if (measureTileSize > 0) { + //Use measureTileSize if set + measureTileHeight = measureTileSize; + measureTileWidth = measureTileSize; + } else if (measureTileSize <= 0) { + if (measureTileWidth <= 0) { + //Set width to default if no value were set + measureTileWidth = dpToPx(DEFAULT_TILE_SIZE_DP); + } + if (measureTileHeight <= 0) { + //Set height to default if no value were set + measureTileHeight = dpToPx(DEFAULT_TILE_SIZE_DP); + } + } + + //Calculate our size based off our measured tile size + int measuredWidth = measureTileWidth * DEFAULT_DAYS_IN_WEEK; + int measuredHeight = measureTileHeight * viewTileHeight; + + //Put padding back in from when we took it away + measuredWidth += getPaddingLeft() + getPaddingRight(); + measuredHeight += getPaddingTop() + getPaddingBottom(); + + //Contract fulfilled, setting out measurements + setMeasuredDimension( + //We clamp inline because we want to use un-clamped versions on the children + clampSize(measuredWidth, widthMeasureSpec), + clampSize(measuredHeight, heightMeasureSpec) + ); + + int count = getChildCount(); + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + + LayoutParams p = (LayoutParams) child.getLayoutParams(); + + int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( + DEFAULT_DAYS_IN_WEEK * measureTileWidth, + MeasureSpec.EXACTLY + ); + + int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( + p.height * measureTileHeight, + MeasureSpec.EXACTLY + ); + + child.measure(childWidthMeasureSpec, childHeightMeasureSpec); + } + } + + private int getWeekCountBasedOnMode() { + int weekCount = calendarMode.visibleWeeksCount; + final boolean isInMonthsMode = calendarMode.equals(CalendarMode.MONTHS); + if (isInMonthsMode && mDynamicHeightEnabled && adapter != null && pager != null) { + final LocalDate cal = adapter.getItem(pager.getCurrentItem()).getDate(); + final LocalDate tempLastDay = cal.withDayOfMonth(cal.lengthOfMonth()); + weekCount = tempLastDay.get(WeekFields.of(firstDayOfWeek, 1).weekOfMonth()); + } + return showWeekDays ? weekCount + DAY_NAMES_ROW : weekCount; + } + + /** + * Clamp the size to the measure spec. + * + * @param size Size we want to be + * @param spec Measure spec to clamp against + * @return the appropriate size to pass to {@linkplain View#setMeasuredDimension(int, int)} + */ + private static int clampSize(int size, int spec) { + int specMode = MeasureSpec.getMode(spec); + int specSize = MeasureSpec.getSize(spec); + switch (specMode) { + case MeasureSpec.EXACTLY: { + return specSize; + } + case MeasureSpec.AT_MOST: { + return Math.min(size, specSize); + } + case MeasureSpec.UNSPECIFIED: + default: { + return size; + } + } + } + + /** + * {@inheritDoc} + */ + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + final int count = getChildCount(); + + final int parentLeft = getPaddingLeft(); + final int parentWidth = right - left - parentLeft - getPaddingRight(); + + int childTop = getPaddingTop(); + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == View.GONE) { + continue; + } + + final int width = child.getMeasuredWidth(); + final int height = child.getMeasuredHeight(); + + int delta = (parentWidth - width) / 2; + int childLeft = parentLeft + delta; + + child.layout(childLeft, childTop, childLeft + width, childTop + height); + + childTop += height; + } + } + + /** + * {@inheritDoc} + */ + @Override + public LayoutParams generateLayoutParams(AttributeSet attrs) { + return new LayoutParams(1); + } + + @Override + public boolean shouldDelayChildPressedState() { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { + return p instanceof LayoutParams; + } + + @Override + protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { + return new LayoutParams(1); + } + + @Override + public void onInitializeAccessibilityEvent(@NonNull AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(event); + event.setClassName(MaterialCalendarView.class.getName()); + } + + @Override + public void onInitializeAccessibilityNodeInfo(@NonNull AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName(MaterialCalendarView.class.getName()); + } + + /** + * Simple layout params for MaterialCalendarView. The only variation for layout is height. + */ + protected static class LayoutParams extends MarginLayoutParams { + + /** + * Create a layout that matches parent width, and is X number of tiles high + * + * @param tileHeight view height in number of tiles + */ + public LayoutParams(int tileHeight) { + super(MATCH_PARENT, tileHeight); + } + } + + /** + * Enable or disable the ability to swipe between months. + * + * @param pagingEnabled pass false to disable paging, true to enable (default) + */ + public void setPagingEnabled(boolean pagingEnabled) { + pager.setPagingEnabled(pagingEnabled); + updateUi(); + } + + /** + * @return true if swiping months is enabled, false if disabled. Default is true. + */ + public boolean isPagingEnabled() { + return pager.isPagingEnabled(); + } + + /** + * Preserve the current parameters of the Material Calendar View. + */ + public State state() { + return state; + } + + /** + * Initialize the parameters from scratch. + */ + public StateBuilder newState() { + return new StateBuilder(); + } + + public class State { + private final CalendarMode calendarMode; + private final DayOfWeek firstDayOfWeek; + private final CalendarDay minDate; + private final CalendarDay maxDate; + private final boolean cacheCurrentPosition; + private final boolean showWeekDays; + + private State(final StateBuilder builder) { + calendarMode = builder.calendarMode; + firstDayOfWeek = builder.firstDayOfWeek; + minDate = builder.minDate; + maxDate = builder.maxDate; + cacheCurrentPosition = builder.cacheCurrentPosition; + showWeekDays = builder.showWeekDays; + } + + /** + * Modify parameters from current state. + */ + public StateBuilder edit() { + return new StateBuilder(this); + } + } + + public class StateBuilder { + private CalendarMode calendarMode; + private DayOfWeek firstDayOfWeek; + private boolean cacheCurrentPosition = false; + private CalendarDay minDate = null; + private CalendarDay maxDate = null; + private boolean showWeekDays; - /** - * Set content description for button future - * - * @param description String to use as content description - */ - public void setContentDescriptionArrowFuture(final CharSequence description) { - buttonFuture.setContentDescription(description); + public StateBuilder() { + calendarMode = CalendarMode.MONTHS; + firstDayOfWeek = + LocalDate.now().with(WeekFields.of(Locale.getDefault()).dayOfWeek(), 1).getDayOfWeek(); } - /** - * Set content description for calendar - * - * @param description String to use as content description - */ - public void setContentDescriptionCalendar(final CharSequence description) { - calendarContentDescription = description; + private StateBuilder(final State state) { + calendarMode = state.calendarMode; + firstDayOfWeek = state.firstDayOfWeek; + minDate = state.minDate; + maxDate = state.maxDate; + cacheCurrentPosition = state.cacheCurrentPosition; + showWeekDays = state.showWeekDays; } /** - * Get content description for calendar + * Sets the first day of the week. + *

+ * Uses the {@link DayOfWeek} day constants. * - * @return calendar's content description + * @param day The first day of the week as a {@link DayOfWeek} enum. + * @see java.util.Calendar */ - public CharSequence getCalendarContentDescription() { - return calendarContentDescription != null - ? calendarContentDescription - : getContext().getString(R.string.calendar); + public StateBuilder setFirstDayOfWeek(DayOfWeek day) { + this.firstDayOfWeek = day; + return this; } /** - * Set a formatter for day content description. + * Set calendar display mode. The default mode is Months. + * When switching between modes will select todays date, or the selected date, + * if selection mode is single. * - * @param formatter the new formatter, null for default - */ - public void setDayFormatterContentDescription(DayFormatter formatter) { - adapter.setDayFormatterContentDescription(formatter); - } - - /** - * @return icon used for the left arrow - */ - public Drawable getLeftArrowMask() { - return leftArrowMask; - } - - /** - * @param icon the new icon to use for the left paging arrow - */ - public void setLeftArrowMask(Drawable icon) { - leftArrowMask = icon; - buttonPast.setImageDrawable(icon); - } - - /** - * @return icon used for the right arrow + * @param mode - calendar mode */ - public Drawable getRightArrowMask() { - return rightArrowMask; + public StateBuilder setCalendarDisplayMode(CalendarMode mode) { + this.calendarMode = mode; + return this; } /** - * @param icon the new icon to use for the right paging arrow + * @param date set the minimum selectable date, null for no minimum */ - public void setRightArrowMask(Drawable icon) { - rightArrowMask = icon; - buttonFuture.setImageDrawable(icon); + public StateBuilder setMinimumDate(@Nullable LocalDate date) { + setMinimumDate(CalendarDay.from(date)); + return this; } /** - * @param resourceId The text appearance resource id. + * @param calendar set the minimum selectable date, null for no minimum */ - public void setHeaderTextAppearance(int resourceId) { - title.setTextAppearance(getContext(), resourceId); + public StateBuilder setMinimumDate(@Nullable CalendarDay calendar) { + minDate = calendar; + return this; } /** - * @param resourceId The text appearance resource id. + * @param date set the maximum selectable date, null for no maximum */ - public void setDateTextAppearance(int resourceId) { - adapter.setDateTextAppearance(resourceId); + public StateBuilder setMaximumDate(@Nullable LocalDate date) { + setMaximumDate(CalendarDay.from(date)); + return this; } /** - * @param resourceId The text appearance resource id. + * @param calendar set the maximum selectable date, null for no maximum */ - public void setWeekDayTextAppearance(int resourceId) { - adapter.setWeekDayTextAppearance(resourceId); + public StateBuilder setMaximumDate(@Nullable CalendarDay calendar) { + maxDate = calendar; + return this; } /** - * Get the currently selected date, or null if no selection. Depending on the selection mode, - * you might get different results. - * - *

For {@link #SELECTION_MODE_SINGLE}, returns the selected date.

- *

For {@link #SELECTION_MODE_MULTIPLE}, returns the last date selected.

- *

For {@link #SELECTION_MODE_RANGE}, returns the last date of the range. In most cases, you should probably be using {@link #getSelectedDates()}.

- *

For {@link #SELECTION_MODE_NONE}, returns null.

- * - * @return The selected day, or null if no selection. If in multiple selection mode, this - * will return the last date of the list of selected dates. - * @see MaterialCalendarView#getSelectedDates() + * @param showWeekDays true to show week days names */ - @Nullable public CalendarDay getSelectedDate() { - List dates = adapter.getSelectedDates(); - if (dates.isEmpty()) { - return null; - } else { - return dates.get(dates.size() - 1); - } + public StateBuilder setShowWeekDays(boolean showWeekDays) { + this.showWeekDays = showWeekDays; + return this; } /** - * Return the list of currently selected dates. Mostly useful for {@link #SELECTION_MODE_MULTIPLE} - * and {@link #SELECTION_MODE_RANGE}. For the other modes, check {@link #getSelectedDate()}. + * Use this method to enable saving the current position when switching + * between week and month mode. By default, the calendar update to the latest selected date + * or the current date. When set to true, the view will used the month that the calendar is + * currently on. * - *

For {@link #SELECTION_MODE_MULTIPLE}, returns the list in the order of selection.

- *

For {@link #SELECTION_MODE_RANGE}, returns the range of dates ordered chronologically.

- * - * @return All of the currently selected dates. - * @see MaterialCalendarView#getSelectedDate() - */ - @NonNull public List getSelectedDates() { - return adapter.getSelectedDates(); - } - - /** - * Clear the currently selected date(s) - */ - public void clearSelection() { - List dates = getSelectedDates(); - adapter.clearSelections(); - for (CalendarDay day : dates) { - dispatchOnDateSelected(day, false); - } - } - - /** - * @param date a Date set to a day to select. Null to clear selection + * @param cacheCurrentPosition Set to true to cache the current position, false otherwise. */ - public void setSelectedDate(@Nullable LocalDate date) { - setSelectedDate(CalendarDay.from(date)); + public StateBuilder isCacheCalendarPositionEnabled(final boolean cacheCurrentPosition) { + this.cacheCurrentPosition = cacheCurrentPosition; + return this; } - /** - * @param date a Date to set as selected. Null to clear selection - */ - public void setSelectedDate(@Nullable CalendarDay date) { - clearSelection(); - if (date != null) { - setDateSelected(date, true); - } + public void commit() { + MaterialCalendarView.this.commit(new State(this)); } + } - /** - * @param day a CalendarDay to change. Passing null does nothing - * @param selected true if day should be selected, false to deselect - */ - public void setDateSelected(@Nullable CalendarDay day, boolean selected) { - if (day == null) { - return; + private void commit(State state) { + // Use the calendarDayToShow to determine which date to focus on for the case of switching between month and week views + CalendarDay calendarDayToShow = null; + if (adapter != null && state.cacheCurrentPosition) { + calendarDayToShow = adapter.getItem(pager.getCurrentItem()); + if (calendarMode != state.calendarMode) { + CalendarDay currentlySelectedDate = getSelectedDate(); + if (calendarMode == CalendarMode.MONTHS && currentlySelectedDate != null) { + // Going from months to weeks + LocalDate lastVisibleCalendar = calendarDayToShow.getDate(); + CalendarDay lastVisibleCalendarDay = CalendarDay.from(lastVisibleCalendar.plusDays(1)); + if (currentlySelectedDate.equals(calendarDayToShow) || + (currentlySelectedDate.isAfter(calendarDayToShow) && currentlySelectedDate.isBefore( + lastVisibleCalendarDay))) { + // Currently selected date is within view, so center on that + calendarDayToShow = currentlySelectedDate; + } + } else if (calendarMode == CalendarMode.WEEKS) { + // Going from weeks to months + LocalDate lastVisibleCalendar = calendarDayToShow.getDate(); + CalendarDay lastVisibleCalendarDay = CalendarDay.from(lastVisibleCalendar.plusDays(6)); + if (currentlySelectedDate != null && + (currentlySelectedDate.equals(calendarDayToShow) || currentlySelectedDate.equals( + lastVisibleCalendarDay) || + (currentlySelectedDate.isAfter(calendarDayToShow) + && currentlySelectedDate.isBefore(lastVisibleCalendarDay)))) { + // Currently selected date is within view, so center on that + calendarDayToShow = currentlySelectedDate; + } else { + calendarDayToShow = lastVisibleCalendarDay; + } } - adapter.setDateSelected(day, selected); - } - - /** - * Get the current first day of the month in month mode, or the first visible day of the - * currently visible week. - * - * For example, in week mode, if the week is July 29th, 2018 to August 4th, 2018, - * this will return July 29th, 2018. If in month mode and the month is august, then this method - * will return August 1st, 2018. - * - * @return The current month or week shown, will be set to first day of the month in month mode, - * or the first visible day for a week. - */ - public CalendarDay getCurrentDate() { - return adapter.getItem(pager.getCurrentItem()); - } - - /** - * Set the calendar to a specific month or week based on a date. - * - * In month mode, the calendar will be set to the corresponding month. - * - * In week mode, the calendar will be set to the corresponding week. - * - * @param calendar a Calendar set to a day to focus the calendar on. Null will do nothing - */ - public void setCurrentDate(@Nullable LocalDate calendar) { - setCurrentDate(CalendarDay.from(calendar)); - } - - /** - * Set the calendar to a specific month or week based on a date. - * - * In month mode, the calendar will be set to the corresponding month. - * - * In week mode, the calendar will be set to the corresponding week. - * - * @param day a CalendarDay to focus the calendar on. Null will do nothing - */ - public void setCurrentDate(@Nullable CalendarDay day) { - setCurrentDate(day, true); - } - - /** - * Set the calendar to a specific month or week based on a date. - * - * In month mode, the calendar will be set to the corresponding month. - * - * In week mode, the calendar will be set to the corresponding week. - * - * @param day a CalendarDay to focus the calendar on. Null will do nothing - * @param useSmoothScroll use smooth scroll when changing months. - */ - public void setCurrentDate(@Nullable CalendarDay day, boolean useSmoothScroll) { - if (day == null) { - return; - } - int index = adapter.getIndexForDay(day); - pager.setCurrentItem(index, useSmoothScroll); - updateUi(); - } - - /** - * @return the minimum selectable date for the calendar, if any - */ - public CalendarDay getMinimumDate() { - return minDate; - } - - /** - * @return the maximum selectable date for the calendar, if any - */ - public CalendarDay getMaximumDate() { - return maxDate; - } - - /** - * The default value is {@link #SHOW_DEFAULTS}, which currently is just {@link #SHOW_DECORATED_DISABLED}. - * This means that the default visible days are of the current month, in the min-max range. - * - * @param showOtherDates flags for showing non-enabled dates - * @see #SHOW_ALL - * @see #SHOW_NONE - * @see #SHOW_DEFAULTS - * @see #SHOW_OTHER_MONTHS - * @see #SHOW_OUT_OF_RANGE - * @see #SHOW_DECORATED_DISABLED - */ - public void setShowOtherDates(@ShowOtherDates int showOtherDates) { - adapter.setShowOtherDates(showOtherDates); - } - - /** - * Allow the user to click on dates from other months that are not out of range. Go to next or - * previous month if a day outside the current month is clicked. The day still need to be - * enabled to be selected. - * Default value is true. Should be used with {@link #SHOW_OTHER_MONTHS}. - * - * @param enabled True to allow the user to click on a day outside current month displayed - */ - public void setAllowClickDaysOutsideCurrentMonth(final boolean enabled) { - this.allowClickDaysOutsideCurrentMonth = enabled; - } - - /** - * Set a formatter for weekday labels. - * - * @param formatter the new formatter, null for default - */ - public void setWeekDayFormatter(WeekDayFormatter formatter) { - adapter.setWeekDayFormatter(formatter == null ? WeekDayFormatter.DEFAULT : formatter); - } - - /** - * Set a formatter for day labels. - * - * @param formatter the new formatter, null for default - */ - public void setDayFormatter(DayFormatter formatter) { - adapter.setDayFormatter(formatter == null ? DayFormatter.DEFAULT : formatter); - } - - /** - * Set a {@linkplain com.prolificinteractive.materialcalendarview.format.WeekDayFormatter} - * with the provided week day labels - * - * @param weekDayLabels Labels to use for the days of the week - * @see com.prolificinteractive.materialcalendarview.format.ArrayWeekDayFormatter - * @see #setWeekDayFormatter(com.prolificinteractive.materialcalendarview.format.WeekDayFormatter) - */ - public void setWeekDayLabels(CharSequence[] weekDayLabels) { - setWeekDayFormatter(new ArrayWeekDayFormatter(weekDayLabels)); - } - - /** - * Set a {@linkplain com.prolificinteractive.materialcalendarview.format.WeekDayFormatter} - * with the provided week day labels - * - * @param arrayRes String array resource of week day labels - * @see com.prolificinteractive.materialcalendarview.format.ArrayWeekDayFormatter - * @see #setWeekDayFormatter(com.prolificinteractive.materialcalendarview.format.WeekDayFormatter) - */ - public void setWeekDayLabels(@ArrayRes int arrayRes) { - setWeekDayLabels(getResources().getTextArray(arrayRes)); - } - - /** - * @return int of flags used for showing non-enabled dates - * @see #SHOW_ALL - * @see #SHOW_NONE - * @see #SHOW_DEFAULTS - * @see #SHOW_OTHER_MONTHS - * @see #SHOW_OUT_OF_RANGE - * @see #SHOW_DECORATED_DISABLED - */ - @ShowOtherDates - public int getShowOtherDates() { - return adapter.getShowOtherDates(); - } - - /** - * @return true if allow click on days outside current month displayed - */ - public boolean allowClickDaysOutsideCurrentMonth() { - return allowClickDaysOutsideCurrentMonth; - } - - /** - * @return true if the week days names are shown - */ - public boolean isShowWeekDays() { - return showWeekDays; - } - - /** - * Set a custom formatter for the month/year title - * - * @param titleFormatter new formatter to use, null to use default formatter - */ - public void setTitleFormatter(@Nullable TitleFormatter titleFormatter) { - titleChanger.setTitleFormatter(titleFormatter); - adapter.setTitleFormatter(titleFormatter); - updateUi(); - } - - /** - * Set a {@linkplain com.prolificinteractive.materialcalendarview.format.TitleFormatter} - * using the provided month labels - * - * @param monthLabels month labels to use - * @see com.prolificinteractive.materialcalendarview.format.MonthArrayTitleFormatter - * @see #setTitleFormatter(com.prolificinteractive.materialcalendarview.format.TitleFormatter) - */ - public void setTitleMonths(CharSequence[] monthLabels) { - setTitleFormatter(new MonthArrayTitleFormatter(monthLabels)); - } - - /** - * Set a {@linkplain com.prolificinteractive.materialcalendarview.format.TitleFormatter} - * using the provided month labels - * - * @param arrayRes String array resource of month labels to use - * @see com.prolificinteractive.materialcalendarview.format.MonthArrayTitleFormatter - * @see #setTitleFormatter(com.prolificinteractive.materialcalendarview.format.TitleFormatter) - */ - public void setTitleMonths(@ArrayRes int arrayRes) { - setTitleMonths(getResources().getTextArray(arrayRes)); - } - - /** - * Change the title animation orientation to have a different look and feel. - * - * @param orientation {@link MaterialCalendarView#VERTICAL} or {@link MaterialCalendarView#HORIZONTAL} - */ - public void setTitleAnimationOrientation(final int orientation) { - titleChanger.setOrientation(orientation); - } - - /** - * Get the orientation of the animation of the title. - * - * @return Title animation orientation {@link MaterialCalendarView#VERTICAL} or {@link MaterialCalendarView#HORIZONTAL} - */ - public int getTitleAnimationOrientation() { - return titleChanger.getOrientation(); - } - - /** - * Sets the visibility {@link #topbar}, which contains - * the previous month button {@link #buttonPast}, next month button {@link #buttonFuture}, - * and the month title {@link #title}. - * - * @param visible Boolean indicating if the topbar is visible - */ - public void setTopbarVisible(boolean visible) { - topbar.setVisibility(visible ? View.VISIBLE : View.GONE); - requestLayout(); - } - - /** - * @return true if the topbar is visible - */ - public boolean getTopbarVisible() { - return topbar.getVisibility() == View.VISIBLE; - } - - /** - * Get the current {@link CalendarMode} set of the Calendar. - * - * @return Whichever mode the calendar is currently in. - */ - public CalendarMode getCalendarMode() { - return calendarMode; - } - - @Override - protected Parcelable onSaveInstanceState() { - SavedState ss = new SavedState(super.onSaveInstanceState()); - ss.color = getSelectionColor(); - ss.dateTextAppearance = adapter.getDateTextAppearance(); - ss.weekDayTextAppearance = adapter.getWeekDayTextAppearance(); - ss.showOtherDates = getShowOtherDates(); - ss.allowClickDaysOutsideCurrentMonth = allowClickDaysOutsideCurrentMonth(); - ss.minDate = getMinimumDate(); - ss.maxDate = getMaximumDate(); - ss.selectedDates = getSelectedDates(); - ss.firstDayOfWeek = getFirstDayOfWeek(); - ss.orientation = getTitleAnimationOrientation(); - ss.selectionMode = getSelectionMode(); - ss.tileWidthPx = getTileWidth(); - ss.tileHeightPx = getTileHeight(); - ss.topbarVisible = getTopbarVisible(); - ss.calendarMode = calendarMode; - ss.dynamicHeightEnabled = mDynamicHeightEnabled; - ss.currentMonth = currentMonth; - ss.cacheCurrentPosition = state.cacheCurrentPosition; - ss.showWeekDays = showWeekDays; - return ss; - } - - @Override - protected void onRestoreInstanceState(Parcelable state) { - SavedState ss = (SavedState) state; - super.onRestoreInstanceState(ss.getSuperState()); - newState() - .setFirstDayOfWeek(ss.firstDayOfWeek) - .setCalendarDisplayMode(ss.calendarMode) - .setMinimumDate(ss.minDate) - .setMaximumDate(ss.maxDate) - .isCacheCalendarPositionEnabled(ss.cacheCurrentPosition) - .setShowWeekDays(ss.showWeekDays) - .commit(); - - setSelectionColor(ss.color); - setDateTextAppearance(ss.dateTextAppearance); - setWeekDayTextAppearance(ss.weekDayTextAppearance); - setShowOtherDates(ss.showOtherDates); - setAllowClickDaysOutsideCurrentMonth(ss.allowClickDaysOutsideCurrentMonth); - clearSelection(); - for (CalendarDay calendarDay : ss.selectedDates) { - setDateSelected(calendarDay, true); - } - setTitleAnimationOrientation(ss.orientation); - setTileWidth(ss.tileWidthPx); - setTileHeight(ss.tileHeightPx); - setTopbarVisible(ss.topbarVisible); - setSelectionMode(ss.selectionMode); - setDynamicHeightEnabled(ss.dynamicHeightEnabled); - setCurrentDate(ss.currentMonth); - } - - @Override - protected void dispatchSaveInstanceState(@NonNull SparseArray container) { - dispatchFreezeSelfOnly(container); - } - - @Override - protected void dispatchRestoreInstanceState(@NonNull SparseArray container) { - dispatchThawSelfOnly(container); - } - - private void setRangeDates(CalendarDay min, CalendarDay max) { - CalendarDay c = currentMonth; - adapter.setRangeDates(min, max); - currentMonth = c; - if (min != null) { - currentMonth = min.isAfter(currentMonth) ? min : currentMonth; - } - int position = adapter.getIndexForDay(c); - pager.setCurrentItem(position, false); - updateUi(); - } - - public static class SavedState extends BaseSavedState { - - int color = 0; - int dateTextAppearance = 0; - int weekDayTextAppearance = 0; - int showOtherDates = SHOW_DEFAULTS; - boolean allowClickDaysOutsideCurrentMonth = true; - CalendarDay minDate = null; - CalendarDay maxDate = null; - List selectedDates = new ArrayList<>(); - DayOfWeek firstDayOfWeek = WeekFields.of(Locale.getDefault()).getFirstDayOfWeek(); - int orientation = 0; - int tileWidthPx = -1; - int tileHeightPx = -1; - boolean topbarVisible = true; - int selectionMode = SELECTION_MODE_SINGLE; - boolean dynamicHeightEnabled = false; - CalendarMode calendarMode = CalendarMode.MONTHS; - CalendarDay currentMonth = null; - boolean cacheCurrentPosition; - boolean showWeekDays; - - SavedState(Parcelable superState) { - super(superState); - } - - @Override - public void writeToParcel(@NonNull Parcel out, int flags) { - super.writeToParcel(out, flags); - out.writeInt(color); - out.writeInt(dateTextAppearance); - out.writeInt(weekDayTextAppearance); - out.writeInt(showOtherDates); - out.writeByte((byte) (allowClickDaysOutsideCurrentMonth ? 1 : 0)); - out.writeParcelable(minDate, 0); - out.writeParcelable(maxDate, 0); - out.writeTypedList(selectedDates); - out.writeInt(firstDayOfWeek.getValue()); - out.writeInt(orientation); - out.writeInt(tileWidthPx); - out.writeInt(tileHeightPx); - out.writeInt(topbarVisible ? 1 : 0); - out.writeInt(selectionMode); - out.writeInt(dynamicHeightEnabled ? 1 : 0); - out.writeInt(calendarMode == CalendarMode.WEEKS ? 1 : 0); - out.writeParcelable(currentMonth, 0); - out.writeByte((byte) (cacheCurrentPosition ? 1 : 0)); - out.writeByte((byte) (showWeekDays ? 1 : 0)); - } - - public static final Parcelable.Creator CREATOR - = new Parcelable.Creator() { - public SavedState createFromParcel(Parcel in) { - return new SavedState(in); - } - - public SavedState[] newArray(int size) { - return new SavedState[size]; - } - }; - - private SavedState(Parcel in) { - super(in); - color = in.readInt(); - dateTextAppearance = in.readInt(); - weekDayTextAppearance = in.readInt(); - showOtherDates = in.readInt(); - allowClickDaysOutsideCurrentMonth = in.readByte() != 0; - ClassLoader loader = CalendarDay.class.getClassLoader(); - minDate = in.readParcelable(loader); - maxDate = in.readParcelable(loader); - in.readTypedList(selectedDates, CalendarDay.CREATOR); - firstDayOfWeek = DayOfWeek.of(in.readInt()); - orientation = in.readInt(); - tileWidthPx = in.readInt(); - tileHeightPx = in.readInt(); - topbarVisible = in.readInt() == 1; - selectionMode = in.readInt(); - dynamicHeightEnabled = in.readInt() == 1; - calendarMode = in.readInt() == 1 ? CalendarMode.WEEKS : CalendarMode.MONTHS; - currentMonth = in.readParcelable(loader); - cacheCurrentPosition = in.readByte() != 0; - showWeekDays = in.readByte() != 0; - } - } - - private static int getThemeAccentColor(Context context) { - int colorAttr; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - colorAttr = android.R.attr.colorAccent; - } else { - //Get colorAccent defined for AppCompat - colorAttr = context.getResources().getIdentifier("colorAccent", "attr", context.getPackageName()); - } - TypedValue outValue = new TypedValue(); - context.getTheme().resolveAttribute(colorAttr, outValue, true); - return outValue.data; - } - - /** - * @return The first day of the week as a {@linkplain Calendar} day constant. - */ - public DayOfWeek getFirstDayOfWeek() { - return firstDayOfWeek; - } - - /** - * By default, the calendar will take up all the space needed to show any month (6 rows). - * By enabling dynamic height, the view will change height dependant on the visible month. - *

- * This means months that only need 5 or 4 rows to show the entire month will only take up - * that many rows, and will grow and shrink as necessary. - * - * @param useDynamicHeight true to have the view different heights based on the visible month - */ - public void setDynamicHeightEnabled(boolean useDynamicHeight) { - this.mDynamicHeightEnabled = useDynamicHeight; - } - - /** - * @return the dynamic height state - true if enabled. - */ - public boolean isDynamicHeightEnabled() { - return mDynamicHeightEnabled; - } - - - /** - * Add a collection of day decorators - * - * @param decorators decorators to add - */ - public void addDecorators(Collection decorators) { - if (decorators == null) { - return; - } - - dayViewDecorators.addAll(decorators); - adapter.setDecorators(dayViewDecorators); - } - - /** - * Add several day decorators - * - * @param decorators decorators to add - */ - public void addDecorators(DayViewDecorator... decorators) { - addDecorators(Arrays.asList(decorators)); - } - - /** - * Add a day decorator - * - * @param decorator decorator to add - */ - public void addDecorator(DayViewDecorator decorator) { - if (decorator == null) { - return; - } - dayViewDecorators.add(decorator); - adapter.setDecorators(dayViewDecorators); - } - - /** - * Remove all decorators - */ - public void removeDecorators() { - dayViewDecorators.clear(); - adapter.setDecorators(dayViewDecorators); - } - - /** - * Remove a specific decorator instance. Same rules as {@linkplain List#remove(Object)} - * - * @param decorator decorator to remove - */ - public void removeDecorator(DayViewDecorator decorator) { - dayViewDecorators.remove(decorator); - adapter.setDecorators(dayViewDecorators); - } - - /** - * Invalidate decorators after one has changed internally. That is, if a decorator mutates, you - * should call this method to update the widget. - */ - public void invalidateDecorators() { - adapter.invalidateDecorators(); - } - - /* - * Listener/Callback Code - */ - - /** - * Sets the listener to be notified upon selected date changes. - * - * @param listener thing to be notified - */ - public void setOnDateChangedListener(OnDateSelectedListener listener) { - this.listener = listener; - } - - /** - * Sets the listener to be notified upon long clicks on dates. - * - * @param longClickListener thing to be notified - */ - public void setOnDateLongClickListener(OnDateLongClickListener longClickListener) { - this.longClickListener = longClickListener; - } - - /** - * Sets the listener to be notified upon month changes. - * - * @param listener thing to be notified - */ - public void setOnMonthChangedListener(OnMonthChangedListener listener) { - this.monthListener = listener; - } - - /** - * Sets the listener to be notified upon a range has been selected. - * - * @param listener thing to be notified - */ - public void setOnRangeSelectedListener(OnRangeSelectedListener listener) { - this.rangeListener = listener; - } - - /** - * Add listener to the title or null to remove it. - * - * @param listener Listener to be notified. - */ - public void setOnTitleClickListener(final OnClickListener listener) { - title.setOnClickListener(listener); - } - - /** - * Dispatch date change events to a listener, if set - * - * @param day the day that was selected - * @param selected true if the day is now currently selected, false otherwise - */ - protected void dispatchOnDateSelected(final CalendarDay day, final boolean selected) { - if (listener != null) { - listener.onDateSelected(MaterialCalendarView.this, day, selected); - } - } - - /** - * Dispatch a range of days to a range listener, if set, ordered chronologically. - * - * @param days Enclosing days ordered from first to last day. - */ - protected void dispatchOnRangeSelected(@NonNull final List days) { - if (rangeListener != null) { - rangeListener.onRangeSelected(MaterialCalendarView.this, days); - } - } - - /** - * Dispatch date change events to a listener, if set - * - * @param day first day of the new month - */ - protected void dispatchOnMonthChanged(final CalendarDay day) { - if (monthListener != null) { - monthListener.onMonthChanged(MaterialCalendarView.this, day); - } - } - - /** - * Call by {@link CalendarPagerView} to indicate that a day was clicked and we should handle it. - * This method will always process the click to the selected date. - * - * @param date date of the day that was clicked - * @param nowSelected true if the date is now selected, false otherwise - */ - protected void onDateClicked(@NonNull CalendarDay date, boolean nowSelected) { - switch (selectionMode) { - case SELECTION_MODE_MULTIPLE: { - adapter.setDateSelected(date, nowSelected); - dispatchOnDateSelected(date, nowSelected); - } - break; - case SELECTION_MODE_RANGE: { - final List currentSelection = adapter.getSelectedDates(); - - if (currentSelection.size() == 0) { - // Selecting the first date of a range - adapter.setDateSelected(date, nowSelected); - dispatchOnDateSelected(date, nowSelected); - } else if (currentSelection.size() == 1) { - // Selecting the second date of a range - final CalendarDay firstDaySelected = currentSelection.get(0); - if (firstDaySelected.equals(date)) { - // Right now, we are not supporting a range of one day, so we are removing the day instead. - adapter.setDateSelected(date, nowSelected); - dispatchOnDateSelected(date, nowSelected); - } else if (firstDaySelected.isAfter(date)) { - // Selecting a range, dispatching in reverse order... - adapter.selectRange(date, firstDaySelected); - dispatchOnRangeSelected(adapter.getSelectedDates()); - } else { - // Selecting a range, dispatching in order... - adapter.selectRange(firstDaySelected, date); - dispatchOnRangeSelected(adapter.getSelectedDates()); - } - } else { - // Clearing selection and making a selection of the new date. - adapter.clearSelections(); - adapter.setDateSelected(date, nowSelected); - dispatchOnDateSelected(date, nowSelected); - } - } - break; - default: - case SELECTION_MODE_SINGLE: { - adapter.clearSelections(); - adapter.setDateSelected(date, true); - dispatchOnDateSelected(date, true); - } - break; - } - } - - /** - * Select a fresh range of date including first day and last day. - * - * @param firstDay first day of the range to select - * @param lastDay last day of the range to select - */ - public void selectRange(final CalendarDay firstDay, final CalendarDay lastDay) { - if (firstDay == null || lastDay == null) { - return; - } else if (firstDay.isAfter(lastDay)) { - adapter.selectRange(lastDay, firstDay); - dispatchOnRangeSelected(adapter.getSelectedDates()); - } else { - adapter.selectRange(firstDay, lastDay); - dispatchOnRangeSelected(adapter.getSelectedDates()); - } - } - - /** - * Call by {@link CalendarPagerView} to indicate that a day was clicked and we should handle it - * - * @param dayView - */ - protected void onDateClicked(final DayView dayView) { - final CalendarDay currentDate = getCurrentDate(); - final CalendarDay selectedDate = dayView.getDate(); - final int currentMonth = currentDate.getMonth(); - final int selectedMonth = selectedDate.getMonth(); - - if (calendarMode == CalendarMode.MONTHS - && allowClickDaysOutsideCurrentMonth - && currentMonth != selectedMonth) { - if (currentDate.isAfter(selectedDate)) { - goToPrevious(); - } else if (currentDate.isBefore(selectedDate)) { - goToNext(); - } - } - onDateClicked(dayView.getDate(), !dayView.isChecked()); - - } - - /** - * Call by {@link CalendarPagerView} to indicate that a day was long clicked and we should handle it - * - * @param dayView - */ - protected void onDateLongClicked(final DayView dayView) { - if (longClickListener != null) { - longClickListener.onDateLongClick(MaterialCalendarView.this, dayView.getDate()); - } - } - - /** - * Called by the adapter for cases when changes in state result in dates being unselected - * - * @param date date that should be de-selected - */ - protected void onDateUnselected(CalendarDay date) { - dispatchOnDateSelected(date, false); - } - - /* - * Show Other Dates Utils - */ - - /** - * @param showOtherDates int flag for show other dates - * @return true if the other months flag is set - */ - public static boolean showOtherMonths(@ShowOtherDates int showOtherDates) { - return (showOtherDates & SHOW_OTHER_MONTHS) != 0; - } - - /** - * @param showOtherDates int flag for show other dates - * @return true if the out of range flag is set - */ - public static boolean showOutOfRange(@ShowOtherDates int showOtherDates) { - return (showOtherDates & SHOW_OUT_OF_RANGE) != 0; - } - - /** - * @param showOtherDates int flag for show other dates - * @return true if the decorated disabled flag is set - */ - public static boolean showDecoratedDisabled(@ShowOtherDates int showOtherDates) { - return (showOtherDates & SHOW_DECORATED_DISABLED) != 0; - } - - /* - * Custom ViewGroup Code - */ - - /** - * {@inheritDoc} - */ - @Override - protected LayoutParams generateDefaultLayoutParams() { - return new LayoutParams(1); - } - - /** - * {@inheritDoc} - */ - @Override - protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { - final int specWidthSize = MeasureSpec.getSize(widthMeasureSpec); - final int specWidthMode = MeasureSpec.getMode(widthMeasureSpec); - final int specHeightSize = MeasureSpec.getSize(heightMeasureSpec); - final int specHeightMode = MeasureSpec.getMode(heightMeasureSpec); - - //We need to disregard padding for a while. This will be added back later - final int desiredWidth = specWidthSize - getPaddingLeft() - getPaddingRight(); - final int desiredHeight = specHeightSize - getPaddingTop() - getPaddingBottom(); - - final int weekCount = getWeekCountBasedOnMode(); - - final int viewTileHeight = getTopbarVisible() ? (weekCount + 1) : weekCount; - - //Calculate independent tile sizes for later - int desiredTileWidth = desiredWidth / DEFAULT_DAYS_IN_WEEK; - int desiredTileHeight = desiredHeight / viewTileHeight; - - int measureTileSize = -1; - int measureTileWidth = -1; - int measureTileHeight = -1; - - if (this.tileWidth != INVALID_TILE_DIMENSION || this.tileHeight != INVALID_TILE_DIMENSION) { - if (this.tileWidth > 0) { - //We have a tileWidth set, we should use that - measureTileWidth = this.tileWidth; - } else { - measureTileWidth = desiredTileWidth; - } - if (this.tileHeight > 0) { - //We have a tileHeight set, we should use that - measureTileHeight = this.tileHeight; - } else { - measureTileHeight = desiredTileHeight; - } - } else if (specWidthMode == MeasureSpec.EXACTLY || specWidthMode == MeasureSpec.AT_MOST) { - if (specHeightMode == MeasureSpec.EXACTLY) { - //Pick the smaller of the two explicit sizes - measureTileSize = Math.min(desiredTileWidth, desiredTileHeight); - } else { - //Be the width size the user wants - measureTileSize = desiredTileWidth; - } - } else if (specHeightMode == MeasureSpec.EXACTLY || specHeightMode == MeasureSpec.AT_MOST) { - //Be the height size the user wants - measureTileSize = desiredTileHeight; - } - - if (measureTileSize > 0) { - //Use measureTileSize if set - measureTileHeight = measureTileSize; - measureTileWidth = measureTileSize; - } else if (measureTileSize <= 0) { - if (measureTileWidth <= 0) { - //Set width to default if no value were set - measureTileWidth = dpToPx(DEFAULT_TILE_SIZE_DP); - } - if (measureTileHeight <= 0) { - //Set height to default if no value were set - measureTileHeight = dpToPx(DEFAULT_TILE_SIZE_DP); - } - } - - //Calculate our size based off our measured tile size - int measuredWidth = measureTileWidth * DEFAULT_DAYS_IN_WEEK; - int measuredHeight = measureTileHeight * viewTileHeight; - - //Put padding back in from when we took it away - measuredWidth += getPaddingLeft() + getPaddingRight(); - measuredHeight += getPaddingTop() + getPaddingBottom(); - - //Contract fulfilled, setting out measurements - setMeasuredDimension( - //We clamp inline because we want to use un-clamped versions on the children - clampSize(measuredWidth, widthMeasureSpec), - clampSize(measuredHeight, heightMeasureSpec) - ); - - int count = getChildCount(); - - for (int i = 0; i < count; i++) { - final View child = getChildAt(i); - - LayoutParams p = (LayoutParams) child.getLayoutParams(); - - int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( - DEFAULT_DAYS_IN_WEEK * measureTileWidth, - MeasureSpec.EXACTLY - ); - - int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( - p.height * measureTileHeight, - MeasureSpec.EXACTLY - ); - - child.measure(childWidthMeasureSpec, childHeightMeasureSpec); - } - } - - private int getWeekCountBasedOnMode() { - int weekCount = calendarMode.visibleWeeksCount; - final boolean isInMonthsMode = calendarMode.equals(CalendarMode.MONTHS); - if (isInMonthsMode && mDynamicHeightEnabled && adapter != null && pager != null) { - final LocalDate cal = adapter.getItem(pager.getCurrentItem()).getDate(); - final LocalDate tempLastDay = cal.withDayOfMonth(cal.lengthOfMonth()); - weekCount = tempLastDay.get(WeekFields.of(firstDayOfWeek, 1).weekOfMonth()); - } - return showWeekDays ? weekCount + DAY_NAMES_ROW : weekCount; - } - - /** - * Clamp the size to the measure spec. - * - * @param size Size we want to be - * @param spec Measure spec to clamp against - * @return the appropriate size to pass to {@linkplain View#setMeasuredDimension(int, int)} - */ - private static int clampSize(int size, int spec) { - int specMode = MeasureSpec.getMode(spec); - int specSize = MeasureSpec.getSize(spec); - switch (specMode) { - case MeasureSpec.EXACTLY: { - return specSize; - } - case MeasureSpec.AT_MOST: { - return Math.min(size, specSize); - } - case MeasureSpec.UNSPECIFIED: - default: { - return size; - } - } - } - - /** - * {@inheritDoc} - */ - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - final int count = getChildCount(); - - final int parentLeft = getPaddingLeft(); - final int parentWidth = right - left - parentLeft - getPaddingRight(); - - int childTop = getPaddingTop(); - - for (int i = 0; i < count; i++) { - final View child = getChildAt(i); - if (child.getVisibility() == View.GONE) { - continue; - } - - final int width = child.getMeasuredWidth(); - final int height = child.getMeasuredHeight(); - - int delta = (parentWidth - width) / 2; - int childLeft = parentLeft + delta; - - child.layout(childLeft, childTop, childLeft + width, childTop + height); - - childTop += height; - } - } - - /** - * {@inheritDoc} - */ - @Override - public LayoutParams generateLayoutParams(AttributeSet attrs) { - return new LayoutParams(1); - } - - @Override - public boolean shouldDelayChildPressedState() { - return false; - } - - /** - * {@inheritDoc} - */ - @Override - protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { - return p instanceof LayoutParams; - } - - @Override - protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { - return new LayoutParams(1); - } - - - @Override - public void onInitializeAccessibilityEvent(@NonNull AccessibilityEvent event) { - super.onInitializeAccessibilityEvent(event); - event.setClassName(MaterialCalendarView.class.getName()); - } - - @Override - public void onInitializeAccessibilityNodeInfo(@NonNull AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfo(info); - info.setClassName(MaterialCalendarView.class.getName()); - } - - /** - * Simple layout params for MaterialCalendarView. The only variation for layout is height. - */ - protected static class LayoutParams extends MarginLayoutParams { - - /** - * Create a layout that matches parent width, and is X number of tiles high - * - * @param tileHeight view height in number of tiles - */ - public LayoutParams(int tileHeight) { - super(MATCH_PARENT, tileHeight); - } - - } - - /** - * Enable or disable the ability to swipe between months. - * - * @param pagingEnabled pass false to disable paging, true to enable (default) - */ - public void setPagingEnabled(boolean pagingEnabled) { - pager.setPagingEnabled(pagingEnabled); - updateUi(); - } - - /** - * @return true if swiping months is enabled, false if disabled. Default is true. - */ - public boolean isPagingEnabled() { - return pager.isPagingEnabled(); - } - - /** - * Preserve the current parameters of the Material Calendar View. - */ - public State state() { - return state; - } - - /** - * Initialize the parameters from scratch. - */ - public StateBuilder newState() { - return new StateBuilder(); - } - - public class State { - private final CalendarMode calendarMode; - private final DayOfWeek firstDayOfWeek; - private final CalendarDay minDate; - private final CalendarDay maxDate; - private final boolean cacheCurrentPosition; - private final boolean showWeekDays; - - private State(final StateBuilder builder) { - calendarMode = builder.calendarMode; - firstDayOfWeek = builder.firstDayOfWeek; - minDate = builder.minDate; - maxDate = builder.maxDate; - cacheCurrentPosition = builder.cacheCurrentPosition; - showWeekDays = builder.showWeekDays; - } - - /** - * Modify parameters from current state. - */ - public StateBuilder edit() { - return new StateBuilder(this); - } - - } - - public class StateBuilder { - private CalendarMode calendarMode; - private DayOfWeek firstDayOfWeek; - private boolean cacheCurrentPosition = false; - private CalendarDay minDate = null; - private CalendarDay maxDate = null; - private boolean showWeekDays; - - public StateBuilder() { - calendarMode = CalendarMode.MONTHS; - firstDayOfWeek = - LocalDate.now().with(WeekFields.of(Locale.getDefault()).dayOfWeek(), 1).getDayOfWeek(); - } - - private StateBuilder(final State state) { - calendarMode = state.calendarMode; - firstDayOfWeek = state.firstDayOfWeek; - minDate = state.minDate; - maxDate = state.maxDate; - cacheCurrentPosition = state.cacheCurrentPosition; - showWeekDays = state.showWeekDays; - } - - /** - * Sets the first day of the week. - *

- * Uses the {@link DayOfWeek} day constants. - * - * @param day The first day of the week as a {@link DayOfWeek} enum. - * @see java.util.Calendar - */ - public StateBuilder setFirstDayOfWeek(DayOfWeek day) { - this.firstDayOfWeek = day; - return this; - } - - /** - * Set calendar display mode. The default mode is Months. - * When switching between modes will select todays date, or the selected date, - * if selection mode is single. - * - * @param mode - calendar mode - */ - public StateBuilder setCalendarDisplayMode(CalendarMode mode) { - this.calendarMode = mode; - return this; - } - - /** - * @param date set the minimum selectable date, null for no minimum - */ - public StateBuilder setMinimumDate(@Nullable LocalDate date) { - setMinimumDate(CalendarDay.from(date)); - return this; - } - - /** - * @param calendar set the minimum selectable date, null for no minimum - */ - public StateBuilder setMinimumDate(@Nullable CalendarDay calendar) { - minDate = calendar; - return this; - } - - /** - * @param date set the maximum selectable date, null for no maximum - */ - public StateBuilder setMaximumDate(@Nullable LocalDate date) { - setMaximumDate(CalendarDay.from(date)); - return this; - } - - /** - * @param calendar set the maximum selectable date, null for no maximum - */ - public StateBuilder setMaximumDate(@Nullable CalendarDay calendar) { - maxDate = calendar; - return this; - } - - /** - * @param showWeekDays true to show week days names - */ - public StateBuilder setShowWeekDays(boolean showWeekDays) { - this.showWeekDays = showWeekDays; - return this; - } - - /** - * Use this method to enable saving the current position when switching - * between week and month mode. By default, the calendar update to the latest selected date - * or the current date. When set to true, the view will used the month that the calendar is - * currently on. - * - * @param cacheCurrentPosition Set to true to cache the current position, false otherwise. - */ - public StateBuilder isCacheCalendarPositionEnabled(final boolean cacheCurrentPosition) { - this.cacheCurrentPosition = cacheCurrentPosition; - return this; - } - - public void commit() { - MaterialCalendarView.this.commit(new State(this)); - } - } - - private void commit(State state) { - // Use the calendarDayToShow to determine which date to focus on for the case of switching between month and week views - CalendarDay calendarDayToShow = null; - if (adapter != null && state.cacheCurrentPosition) { - calendarDayToShow = adapter.getItem(pager.getCurrentItem()); - if (calendarMode != state.calendarMode) { - CalendarDay currentlySelectedDate = getSelectedDate(); - if (calendarMode == CalendarMode.MONTHS && currentlySelectedDate != null) { - // Going from months to weeks - LocalDate lastVisibleCalendar = calendarDayToShow.getDate(); - CalendarDay lastVisibleCalendarDay = CalendarDay.from(lastVisibleCalendar.plusDays(1)); - if (currentlySelectedDate.equals(calendarDayToShow) || - (currentlySelectedDate.isAfter(calendarDayToShow) && currentlySelectedDate.isBefore(lastVisibleCalendarDay))) { - // Currently selected date is within view, so center on that - calendarDayToShow = currentlySelectedDate; - } - } else if (calendarMode == CalendarMode.WEEKS) { - // Going from weeks to months - LocalDate lastVisibleCalendar = calendarDayToShow.getDate(); - CalendarDay lastVisibleCalendarDay = CalendarDay.from(lastVisibleCalendar.plusDays(6)); - if (currentlySelectedDate != null && - (currentlySelectedDate.equals(calendarDayToShow) || currentlySelectedDate.equals(lastVisibleCalendarDay) || - (currentlySelectedDate.isAfter(calendarDayToShow) && currentlySelectedDate.isBefore(lastVisibleCalendarDay)))) { - // Currently selected date is within view, so center on that - calendarDayToShow = currentlySelectedDate; - } else { - calendarDayToShow = lastVisibleCalendarDay; - } - } - } - } - - this.state = state; - // Save states parameters - calendarMode = state.calendarMode; - firstDayOfWeek = state.firstDayOfWeek; - minDate = state.minDate; - maxDate = state.maxDate; - showWeekDays = state.showWeekDays; - - // Recreate adapter - final CalendarPagerAdapter newAdapter; - switch (calendarMode) { - case MONTHS: - newAdapter = new MonthPagerAdapter(this); - break; - case WEEKS: - newAdapter = new WeekPagerAdapter(this); - break; - default: - throw new IllegalArgumentException("Provided display mode which is not yet implemented"); - } - if (adapter == null) { - adapter = newAdapter; - } else { - adapter = adapter.migrateStateAndReturn(newAdapter); - } - adapter.setShowWeekDays(showWeekDays); - pager.setAdapter(adapter); - setRangeDates(minDate, maxDate); - - // Reset height params after mode change - int tileHeight = showWeekDays ? calendarMode.visibleWeeksCount + DAY_NAMES_ROW : calendarMode.visibleWeeksCount; - pager.setLayoutParams(new LayoutParams(tileHeight)); - - setCurrentDate( - selectionMode == SELECTION_MODE_SINGLE && !adapter.getSelectedDates().isEmpty() - ? adapter.getSelectedDates().get(0) - : CalendarDay.today()); - - if (calendarDayToShow != null) { - pager.setCurrentItem(adapter.getIndexForDay(calendarDayToShow)); - } - - invalidateDecorators(); - updateUi(); - } + } + } + + this.state = state; + // Save states parameters + calendarMode = state.calendarMode; + firstDayOfWeek = state.firstDayOfWeek; + minDate = state.minDate; + maxDate = state.maxDate; + showWeekDays = state.showWeekDays; + + // Recreate adapter + final CalendarPagerAdapter newAdapter; + switch (calendarMode) { + case MONTHS: + newAdapter = new MonthPagerAdapter(this); + break; + case WEEKS: + newAdapter = new WeekPagerAdapter(this); + break; + default: + throw new IllegalArgumentException("Provided display mode which is not yet implemented"); + } + if (adapter == null) { + adapter = newAdapter; + } else { + adapter = adapter.migrateStateAndReturn(newAdapter); + } + adapter.setShowWeekDays(showWeekDays); + pager.setAdapter(adapter); + setRangeDates(minDate, maxDate); + + // Reset height params after mode change + int tileHeight = showWeekDays ? calendarMode.visibleWeeksCount + DAY_NAMES_ROW + : calendarMode.visibleWeeksCount; + pager.setLayoutParams(new LayoutParams(tileHeight)); + + setCurrentDate( + selectionMode == SELECTION_MODE_SINGLE && !adapter.getSelectedDates().isEmpty() + ? adapter.getSelectedDates().get(0) + : CalendarDay.today()); + + if (calendarDayToShow != null) { + pager.setCurrentItem(adapter.getIndexForDay(calendarDayToShow)); + } + + invalidateDecorators(); + updateUi(); + } } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/MonthPagerAdapter.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/MonthPagerAdapter.java index 2cbcf03f..1e205310 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/MonthPagerAdapter.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/MonthPagerAdapter.java @@ -1,11 +1,7 @@ package com.prolificinteractive.materialcalendarview; import android.support.annotation.NonNull; -import android.support.v4.util.SparseArrayCompat; -import android.util.Log; -import org.threeten.bp.LocalDate; import org.threeten.bp.Period; -import org.threeten.bp.temporal.ChronoUnit; /** * Pager adapter backing the calendar view diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/MonthView.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/MonthView.java index 9ca3f165..1fae0818 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/MonthView.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/MonthView.java @@ -2,8 +2,6 @@ import android.annotation.SuppressLint; import android.support.annotation.NonNull; - -import java.util.Calendar; import java.util.Collection; import org.threeten.bp.DayOfWeek; import org.threeten.bp.LocalDate; @@ -12,36 +10,37 @@ * Display a month of {@linkplain DayView}s and * seven {@linkplain WeekDayView}s. */ -@SuppressLint("ViewConstructor") -class MonthView extends CalendarPagerView { - - public MonthView( - @NonNull final MaterialCalendarView view, - final CalendarDay month, - final DayOfWeek firstDayOfWeek, - final boolean showWeekDays) { - super(view, month, firstDayOfWeek, showWeekDays); +@SuppressLint("ViewConstructor") class MonthView extends CalendarPagerView { + + public MonthView( + @NonNull final MaterialCalendarView view, + final CalendarDay month, + final DayOfWeek firstDayOfWeek, + final boolean showWeekDays) { + super(view, month, firstDayOfWeek, showWeekDays); + } + + @Override protected void buildDayViews( + final Collection dayViews, + final LocalDate calendar) { + LocalDate temp = calendar; + for (int r = 0; r < DEFAULT_MAX_WEEKS; r++) { + for (int i = 0; i < DEFAULT_DAYS_IN_WEEK; i++) { + addDayView(dayViews, temp); + temp = temp.plusDays(1); + } } + } - @Override protected void buildDayViews(final Collection dayViews, final LocalDate calendar) { - LocalDate temp = calendar; - for (int r = 0; r < DEFAULT_MAX_WEEKS; r++) { - for (int i = 0; i < DEFAULT_DAYS_IN_WEEK; i++) { - addDayView(dayViews, temp); - temp = temp.plusDays(1); - } - } - } + public CalendarDay getMonth() { + return getFirstViewDay(); + } - public CalendarDay getMonth() { - return getFirstViewDay(); - } + @Override protected boolean isDayEnabled(final CalendarDay day) { + return day.getMonth() == getFirstViewDay().getMonth(); + } - @Override protected boolean isDayEnabled(final CalendarDay day) { - return day.getMonth() == getFirstViewDay().getMonth(); - } - - @Override protected int getRows() { - return showWeekDays ? DEFAULT_MAX_WEEKS + DAY_NAMES_ROW : DEFAULT_MAX_WEEKS; - } + @Override protected int getRows() { + return showWeekDays ? DEFAULT_MAX_WEEKS + DAY_NAMES_ROW : DEFAULT_MAX_WEEKS; + } } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/OnDateLongClickListener.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/OnDateLongClickListener.java index 4db93dd2..e1fbc208 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/OnDateLongClickListener.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/OnDateLongClickListener.java @@ -7,12 +7,12 @@ */ public interface OnDateLongClickListener { - /** - * Called when a user long clicks on a day. - * There is no logic to prevent multiple calls for the same date and state. - * - * @param widget the view associated with this listener - * @param date the date that was long clicked. - */ - void onDateLongClick(@NonNull MaterialCalendarView widget, @NonNull CalendarDay date); + /** + * Called when a user long clicks on a day. + * There is no logic to prevent multiple calls for the same date and state. + * + * @param widget the view associated with this listener + * @param date the date that was long clicked. + */ + void onDateLongClick(@NonNull MaterialCalendarView widget, @NonNull CalendarDay date); } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/OnDateSelectedListener.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/OnDateSelectedListener.java index 3769bdc7..e4ea640c 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/OnDateSelectedListener.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/OnDateSelectedListener.java @@ -7,13 +7,16 @@ */ public interface OnDateSelectedListener { - /** - * Called when a user clicks on a day. - * There is no logic to prevent multiple calls for the same date and state. - * - * @param widget the view associated with this listener - * @param date the date that was selected or unselected - * @param selected true if the day is now selected, false otherwise - */ - void onDateSelected(@NonNull MaterialCalendarView widget, @NonNull CalendarDay date, boolean selected); + /** + * Called when a user clicks on a day. + * There is no logic to prevent multiple calls for the same date and state. + * + * @param widget the view associated with this listener + * @param date the date that was selected or unselected + * @param selected true if the day is now selected, false otherwise + */ + void onDateSelected( + @NonNull MaterialCalendarView widget, + @NonNull CalendarDay date, + boolean selected); } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/OnMonthChangedListener.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/OnMonthChangedListener.java index 8b20de65..16f4b576 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/OnMonthChangedListener.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/OnMonthChangedListener.java @@ -5,11 +5,11 @@ */ public interface OnMonthChangedListener { - /** - * Called upon change of the selected day - * - * @param widget the view associated with this listener - * @param date the month picked, as the first day of the month - */ - void onMonthChanged(MaterialCalendarView widget, CalendarDay date); + /** + * Called upon change of the selected day + * + * @param widget the view associated with this listener + * @param date the month picked, as the first day of the month + */ + void onMonthChanged(MaterialCalendarView widget, CalendarDay date); } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/OnRangeSelectedListener.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/OnRangeSelectedListener.java index b157091a..97c41715 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/OnRangeSelectedListener.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/OnRangeSelectedListener.java @@ -1,7 +1,6 @@ package com.prolificinteractive.materialcalendarview; import android.support.annotation.NonNull; - import java.util.List; /** @@ -9,12 +8,12 @@ */ public interface OnRangeSelectedListener { - /** - * Called when a user selects a range of days. - * There is no logic to prevent multiple calls for the same date and state. - * - * @param widget the view associated with this listener - * @param dates the dates in the range, in ascending order - */ - void onRangeSelected(@NonNull MaterialCalendarView widget, @NonNull List dates); + /** + * Called when a user selects a range of days. + * There is no logic to prevent multiple calls for the same date and state. + * + * @param widget the view associated with this listener + * @param dates the dates in the range, in ascending order + */ + void onRangeSelected(@NonNull MaterialCalendarView widget, @NonNull List dates); } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/TitleChanger.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/TitleChanger.java index 6bb56db9..31cef265 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/TitleChanger.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/TitleChanger.java @@ -10,141 +10,140 @@ import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import android.widget.TextView; - import com.prolificinteractive.materialcalendarview.format.TitleFormatter; class TitleChanger { - public static final int DEFAULT_ANIMATION_DELAY = 400; - public static final int DEFAULT_Y_TRANSLATION_DP = 20; + public static final int DEFAULT_ANIMATION_DELAY = 400; + public static final int DEFAULT_Y_TRANSLATION_DP = 20; + + private final TextView title; + @NonNull private TitleFormatter titleFormatter = TitleFormatter.DEFAULT; + + private final int animDelay; + private final int animDuration; + private final int translate; + private final Interpolator interpolator = new DecelerateInterpolator(2f); - private final TextView title; - @NonNull private TitleFormatter titleFormatter = TitleFormatter.DEFAULT; + private int orientation = MaterialCalendarView.VERTICAL; - private final int animDelay; - private final int animDuration; - private final int translate; - private final Interpolator interpolator = new DecelerateInterpolator(2f); + private long lastAnimTime = 0; + private CalendarDay previousMonth = null; - private int orientation = MaterialCalendarView.VERTICAL; + public TitleChanger(TextView title) { + this.title = title; - private long lastAnimTime = 0; - private CalendarDay previousMonth = null; + Resources res = title.getResources(); - public TitleChanger(TextView title) { - this.title = title; + animDelay = DEFAULT_ANIMATION_DELAY; - Resources res = title.getResources(); + animDuration = res.getInteger(android.R.integer.config_shortAnimTime) / 2; - animDelay = DEFAULT_ANIMATION_DELAY; + translate = (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, DEFAULT_Y_TRANSLATION_DP, res.getDisplayMetrics() + ); + } - animDuration = res.getInteger(android.R.integer.config_shortAnimTime) / 2; + public void change(final CalendarDay currentMonth) { + long currentTime = System.currentTimeMillis(); - translate = (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, DEFAULT_Y_TRANSLATION_DP, res.getDisplayMetrics() - ); + if (currentMonth == null) { + return; } - public void change(final CalendarDay currentMonth) { - long currentTime = System.currentTimeMillis(); + if (TextUtils.isEmpty(title.getText()) || (currentTime - lastAnimTime) < animDelay) { + doChange(currentTime, currentMonth, false); + } - if (currentMonth == null) { - return; - } + if (currentMonth.equals(previousMonth) || + (currentMonth.getMonth() == previousMonth.getMonth() + && currentMonth.getYear() == previousMonth.getYear())) { + return; + } - if (TextUtils.isEmpty(title.getText()) || (currentTime - lastAnimTime) < animDelay) { - doChange(currentTime, currentMonth, false); - } + doChange(currentTime, currentMonth, true); + } - if (currentMonth.equals(previousMonth) || - (currentMonth.getMonth() == previousMonth.getMonth() - && currentMonth.getYear() == previousMonth.getYear())) { - return; - } + private void doChange(final long now, final CalendarDay currentMonth, boolean animate) { - doChange(currentTime, currentMonth, true); - } + title.animate().cancel(); + doTranslation(title, 0); - private void doChange(final long now, final CalendarDay currentMonth, boolean animate) { + title.setAlpha(1); + lastAnimTime = now; - title.animate().cancel(); - doTranslation(title, 0); + final CharSequence newTitle = titleFormatter.format(currentMonth); - title.setAlpha(1); - lastAnimTime = now; + if (!animate) { + title.setText(newTitle); + } else { + final int translation = translate * (previousMonth.isBefore(currentMonth) ? 1 : -1); + final ViewPropertyAnimator viewPropertyAnimator = title.animate(); - final CharSequence newTitle = titleFormatter.format(currentMonth); + if (orientation == MaterialCalendarView.HORIZONTAL) { + viewPropertyAnimator.translationX(translation * -1); + } else { + viewPropertyAnimator.translationY(translation * -1); + } - if (!animate) { - title.setText(newTitle); - } else { - final int translation = translate * (previousMonth.isBefore(currentMonth) ? 1 : -1); - final ViewPropertyAnimator viewPropertyAnimator = title.animate(); + viewPropertyAnimator + .alpha(0) + .setDuration(animDuration) + .setInterpolator(interpolator) + .setListener(new AnimatorListener() { - if (orientation == MaterialCalendarView.HORIZONTAL) { - viewPropertyAnimator.translationX(translation * -1); - } else { - viewPropertyAnimator.translationY(translation * -1); + @Override + public void onAnimationCancel(Animator animator) { + doTranslation(title, 0); + title.setAlpha(1); } - viewPropertyAnimator - .alpha(0) - .setDuration(animDuration) - .setInterpolator(interpolator) - .setListener(new AnimatorListener() { - - @Override - public void onAnimationCancel(Animator animator) { - doTranslation(title, 0); - title.setAlpha(1); - } - - @Override - public void onAnimationEnd(Animator animator) { - title.setText(newTitle); - doTranslation(title, translation); - - final ViewPropertyAnimator viewPropertyAnimator = title.animate(); - if (orientation == MaterialCalendarView.HORIZONTAL) { - viewPropertyAnimator.translationX(0); - } else { - viewPropertyAnimator.translationY(0); - } - - viewPropertyAnimator - .alpha(1) - .setDuration(animDuration) - .setInterpolator(interpolator) - .setListener(new AnimatorListener()) - .start(); - } - }).start(); - } - - previousMonth = currentMonth; + @Override + public void onAnimationEnd(Animator animator) { + title.setText(newTitle); + doTranslation(title, translation); + + final ViewPropertyAnimator viewPropertyAnimator = title.animate(); + if (orientation == MaterialCalendarView.HORIZONTAL) { + viewPropertyAnimator.translationX(0); + } else { + viewPropertyAnimator.translationY(0); + } + + viewPropertyAnimator + .alpha(1) + .setDuration(animDuration) + .setInterpolator(interpolator) + .setListener(new AnimatorListener()) + .start(); + } + }).start(); } - private void doTranslation(final TextView title, final int translate) { - if (orientation == MaterialCalendarView.HORIZONTAL) { - title.setTranslationX(translate); - } else { - title.setTranslationY(translate); - } - } + previousMonth = currentMonth; + } - public void setTitleFormatter(@Nullable final TitleFormatter titleFormatter) { - this.titleFormatter = titleFormatter == null ? TitleFormatter.DEFAULT : titleFormatter; + private void doTranslation(final TextView title, final int translate) { + if (orientation == MaterialCalendarView.HORIZONTAL) { + title.setTranslationX(translate); + } else { + title.setTranslationY(translate); } + } - public void setOrientation(int orientation) { - this.orientation = orientation; - } + public void setTitleFormatter(@Nullable final TitleFormatter titleFormatter) { + this.titleFormatter = titleFormatter == null ? TitleFormatter.DEFAULT : titleFormatter; + } - public int getOrientation() { - return orientation; - } + public void setOrientation(int orientation) { + this.orientation = orientation; + } - public void setPreviousMonth(CalendarDay previousMonth) { - this.previousMonth = previousMonth; - } + public int getOrientation() { + return orientation; + } + + public void setPreviousMonth(CalendarDay previousMonth) { + this.previousMonth = previousMonth; + } } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/WeekDayView.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/WeekDayView.java index b6a70ea2..9d635b52 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/WeekDayView.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/WeekDayView.java @@ -6,38 +6,36 @@ import android.support.annotation.Nullable; import android.support.v7.widget.AppCompatTextView; import android.view.Gravity; - import com.prolificinteractive.materialcalendarview.format.WeekDayFormatter; import org.threeten.bp.DayOfWeek; /** * Display a day of the week */ -@SuppressLint("ViewConstructor") -class WeekDayView extends AppCompatTextView { - - private WeekDayFormatter formatter = WeekDayFormatter.DEFAULT; - private DayOfWeek dayOfWeek; +@SuppressLint("ViewConstructor") class WeekDayView extends AppCompatTextView { - public WeekDayView(final Context context, final DayOfWeek dayOfWeek) { - super(context); + private WeekDayFormatter formatter = WeekDayFormatter.DEFAULT; + private DayOfWeek dayOfWeek; - setGravity(Gravity.CENTER); + public WeekDayView(final Context context, final DayOfWeek dayOfWeek) { + super(context); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - setTextAlignment(TEXT_ALIGNMENT_CENTER); - } + setGravity(Gravity.CENTER); - setDayOfWeek(dayOfWeek); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + setTextAlignment(TEXT_ALIGNMENT_CENTER); } - public void setWeekDayFormatter(@Nullable final WeekDayFormatter formatter) { - this.formatter = formatter == null ? WeekDayFormatter.DEFAULT : formatter; - setDayOfWeek(dayOfWeek); - } + setDayOfWeek(dayOfWeek); + } - public void setDayOfWeek(final DayOfWeek dayOfWeek) { - this.dayOfWeek = dayOfWeek; - setText(formatter.format(dayOfWeek)); - } + public void setWeekDayFormatter(@Nullable final WeekDayFormatter formatter) { + this.formatter = formatter == null ? WeekDayFormatter.DEFAULT : formatter; + setDayOfWeek(dayOfWeek); + } + + public void setDayOfWeek(final DayOfWeek dayOfWeek) { + this.dayOfWeek = dayOfWeek; + setText(formatter.format(dayOfWeek)); + } } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/WeekPagerAdapter.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/WeekPagerAdapter.java index 4a7ab7fc..413038da 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/WeekPagerAdapter.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/WeekPagerAdapter.java @@ -1,7 +1,6 @@ package com.prolificinteractive.materialcalendarview; import android.support.annotation.NonNull; - import org.threeten.bp.DayOfWeek; import org.threeten.bp.LocalDate; import org.threeten.bp.temporal.ChronoUnit; diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/WeekView.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/WeekView.java index 6d41c571..b9b87adb 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/WeekView.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/WeekView.java @@ -2,8 +2,6 @@ import android.annotation.SuppressLint; import android.support.annotation.NonNull; - -import java.util.Calendar; import java.util.Collection; import org.threeten.bp.DayOfWeek; import org.threeten.bp.LocalDate; @@ -12,30 +10,31 @@ * Display a week of {@linkplain DayView}s and * seven {@linkplain WeekDayView}s. */ -@SuppressLint("ViewConstructor") -class WeekView extends CalendarPagerView { +@SuppressLint("ViewConstructor") class WeekView extends CalendarPagerView { - public WeekView( - @NonNull final MaterialCalendarView view, - final CalendarDay firstViewDay, - final DayOfWeek firstDayOfWeek, - final boolean showWeekDays) { - super(view, firstViewDay, firstDayOfWeek, showWeekDays); - } + public WeekView( + @NonNull final MaterialCalendarView view, + final CalendarDay firstViewDay, + final DayOfWeek firstDayOfWeek, + final boolean showWeekDays) { + super(view, firstViewDay, firstDayOfWeek, showWeekDays); + } - @Override protected void buildDayViews(final Collection dayViews, final LocalDate calendar) { - LocalDate temp = calendar; - for (int i = 0; i < DEFAULT_DAYS_IN_WEEK; i++) { - addDayView(dayViews, temp); - temp = temp.plusDays(1); - } + @Override protected void buildDayViews( + final Collection dayViews, + final LocalDate calendar) { + LocalDate temp = calendar; + for (int i = 0; i < DEFAULT_DAYS_IN_WEEK; i++) { + addDayView(dayViews, temp); + temp = temp.plusDays(1); } + } - @Override protected boolean isDayEnabled(CalendarDay day) { - return true; - } + @Override protected boolean isDayEnabled(CalendarDay day) { + return true; + } - @Override protected int getRows() { - return showWeekDays ? DAY_NAMES_ROW + 1 : 1; - } + @Override protected int getRows() { + return showWeekDays ? DAY_NAMES_ROW + 1 : 1; + } } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/format/ArrayWeekDayFormatter.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/format/ArrayWeekDayFormatter.java index 4887bde5..f3e052cd 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/format/ArrayWeekDayFormatter.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/format/ArrayWeekDayFormatter.java @@ -7,25 +7,25 @@ */ public class ArrayWeekDayFormatter implements WeekDayFormatter { - private final CharSequence[] weekDayLabels; + private final CharSequence[] weekDayLabels; - /** - * @param weekDayLabels an array of 7 labels, starting with Sunday - */ - public ArrayWeekDayFormatter(final CharSequence[] weekDayLabels) { - if (weekDayLabels == null) { - throw new IllegalArgumentException("Cannot be null"); - } - if (weekDayLabels.length != 7) { - throw new IllegalArgumentException("Array must contain exactly 7 elements"); - } - this.weekDayLabels = weekDayLabels; + /** + * @param weekDayLabels an array of 7 labels, starting with Sunday + */ + public ArrayWeekDayFormatter(final CharSequence[] weekDayLabels) { + if (weekDayLabels == null) { + throw new IllegalArgumentException("Cannot be null"); } - - /** - * {@inheritDoc} - */ - @Override public CharSequence format(final DayOfWeek dayOfWeek) { - return weekDayLabels[dayOfWeek.getValue() - 1]; + if (weekDayLabels.length != 7) { + throw new IllegalArgumentException("Array must contain exactly 7 elements"); } + this.weekDayLabels = weekDayLabels; + } + + /** + * {@inheritDoc} + */ + @Override public CharSequence format(final DayOfWeek dayOfWeek) { + return weekDayLabels[dayOfWeek.getValue() - 1]; + } } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/format/DateFormatDayFormatter.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/format/DateFormatDayFormatter.java index 0a15bccb..cd8e1d37 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/format/DateFormatDayFormatter.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/format/DateFormatDayFormatter.java @@ -1,43 +1,38 @@ package com.prolificinteractive.materialcalendarview.format; import android.support.annotation.NonNull; - import com.prolificinteractive.materialcalendarview.CalendarDay; - import java.text.DateFormat; -import java.text.SimpleDateFormat; import java.util.Locale; import org.threeten.bp.format.DateTimeFormatter; -import static com.prolificinteractive.materialcalendarview.format.TitleFormatter.DEFAULT_FORMAT; - /** * Format using a {@linkplain DateFormat} instance. */ public class DateFormatDayFormatter implements DayFormatter { - private final DateTimeFormatter dateFormat; - - /** - * Format using a default format - */ - public DateFormatDayFormatter() { - this(DateTimeFormatter.ofPattern(DEFAULT_FORMAT, Locale.getDefault())); - } - - /** - * Format using a specific {@linkplain DateFormat} - * - * @param format the format to use - */ - public DateFormatDayFormatter(@NonNull final DateTimeFormatter format) { - this.dateFormat = format; - } - - /** - * {@inheritDoc} - */ - @Override @NonNull public String format(@NonNull final CalendarDay day) { - return dateFormat.format(day.getDate()); - } + private final DateTimeFormatter dateFormat; + + /** + * Format using a default format + */ + public DateFormatDayFormatter() { + this(DateTimeFormatter.ofPattern(DEFAULT_FORMAT, Locale.getDefault())); + } + + /** + * Format using a specific {@linkplain DateFormat} + * + * @param format the format to use + */ + public DateFormatDayFormatter(@NonNull final DateTimeFormatter format) { + this.dateFormat = format; + } + + /** + * {@inheritDoc} + */ + @Override @NonNull public String format(@NonNull final CalendarDay day) { + return dateFormat.format(day.getDate()); + } } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/format/DateFormatTitleFormatter.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/format/DateFormatTitleFormatter.java index e9d65fc9..3ba646c2 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/format/DateFormatTitleFormatter.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/format/DateFormatTitleFormatter.java @@ -1,7 +1,6 @@ package com.prolificinteractive.materialcalendarview.format; import com.prolificinteractive.materialcalendarview.CalendarDay; - import org.threeten.bp.format.DateTimeFormatter; /** @@ -9,28 +8,28 @@ */ public class DateFormatTitleFormatter implements TitleFormatter { - private final DateTimeFormatter dateFormat; + private final DateTimeFormatter dateFormat; - /** - * Format using {@link TitleFormatter#DEFAULT_FORMAT} for formatting. - */ - public DateFormatTitleFormatter() { - this(DateTimeFormatter.ofPattern(DEFAULT_FORMAT)); - } + /** + * Format using {@link TitleFormatter#DEFAULT_FORMAT} for formatting. + */ + public DateFormatTitleFormatter() { + this(DateTimeFormatter.ofPattern(DEFAULT_FORMAT)); + } - /** - * Format using a specified {@linkplain DateTimeFormatter} - * - * @param format the format to use - */ - public DateFormatTitleFormatter(final DateTimeFormatter format) { - this.dateFormat = format; - } + /** + * Format using a specified {@linkplain DateTimeFormatter} + * + * @param format the format to use + */ + public DateFormatTitleFormatter(final DateTimeFormatter format) { + this.dateFormat = format; + } - /** - * {@inheritDoc} - */ - @Override public CharSequence format(final CalendarDay day) { - return dateFormat.format(day.getDate()); - } + /** + * {@inheritDoc} + */ + @Override public CharSequence format(final CalendarDay day) { + return dateFormat.format(day.getDate()); + } } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/format/DayFormatter.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/format/DayFormatter.java index 418ad013..69fc11b8 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/format/DayFormatter.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/format/DayFormatter.java @@ -1,9 +1,7 @@ package com.prolificinteractive.materialcalendarview.format; import android.support.annotation.NonNull; - import com.prolificinteractive.materialcalendarview.CalendarDay; - import java.text.SimpleDateFormat; /** @@ -11,21 +9,21 @@ */ public interface DayFormatter { - /** - * Default format for displaying the day. - */ - String DEFAULT_FORMAT = "d"; + /** + * Default format for displaying the day. + */ + String DEFAULT_FORMAT = "d"; - /** - * Default implementation used by {@linkplain com.prolificinteractive.materialcalendarview.MaterialCalendarView} - */ - DayFormatter DEFAULT = new DateFormatDayFormatter(); + /** + * Default implementation used by {@linkplain com.prolificinteractive.materialcalendarview.MaterialCalendarView} + */ + DayFormatter DEFAULT = new DateFormatDayFormatter(); - /** - * Format a given day into a string - * - * @param day the day - * @return a label for the day - */ - @NonNull String format(@NonNull CalendarDay day); + /** + * Format a given day into a string + * + * @param day the day + * @return a label for the day + */ + @NonNull String format(@NonNull CalendarDay day); } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/format/MonthArrayTitleFormatter.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/format/MonthArrayTitleFormatter.java index c1641bb7..dfd58600 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/format/MonthArrayTitleFormatter.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/format/MonthArrayTitleFormatter.java @@ -1,7 +1,6 @@ package com.prolificinteractive.materialcalendarview.format; import android.text.SpannableStringBuilder; - import com.prolificinteractive.materialcalendarview.CalendarDay; /** @@ -9,31 +8,31 @@ */ public class MonthArrayTitleFormatter implements TitleFormatter { - private final CharSequence[] monthLabels; + private final CharSequence[] monthLabels; - /** - * Format using an array of month labels - * - * @param monthLabels an array of 12 labels to use for months, starting with January - */ - public MonthArrayTitleFormatter(CharSequence[] monthLabels) { - if (monthLabels == null) { - throw new IllegalArgumentException("Label array cannot be null"); - } - if (monthLabels.length < 12) { - throw new IllegalArgumentException("Label array is too short"); - } - this.monthLabels = monthLabels; + /** + * Format using an array of month labels + * + * @param monthLabels an array of 12 labels to use for months, starting with January + */ + public MonthArrayTitleFormatter(CharSequence[] monthLabels) { + if (monthLabels == null) { + throw new IllegalArgumentException("Label array cannot be null"); } - - /** - * {@inheritDoc} - */ - @Override - public CharSequence format(CalendarDay day) { - return new SpannableStringBuilder() - .append(monthLabels[day.getMonth() - 1]) - .append(" ") - .append(String.valueOf(day.getYear())); + if (monthLabels.length < 12) { + throw new IllegalArgumentException("Label array is too short"); } + this.monthLabels = monthLabels; + } + + /** + * {@inheritDoc} + */ + @Override + public CharSequence format(CalendarDay day) { + return new SpannableStringBuilder() + .append(monthLabels[day.getMonth() - 1]) + .append(" ") + .append(String.valueOf(day.getYear())); + } } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/format/TitleFormatter.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/format/TitleFormatter.java index ba8cc6a0..9f2d0d9c 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/format/TitleFormatter.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/format/TitleFormatter.java @@ -7,15 +7,15 @@ */ public interface TitleFormatter { - String DEFAULT_FORMAT = "LLLL yyyy"; + String DEFAULT_FORMAT = "LLLL yyyy"; - TitleFormatter DEFAULT = new DateFormatTitleFormatter(); + TitleFormatter DEFAULT = new DateFormatTitleFormatter(); - /** - * Converts the supplied day to a suitable month/year title - * - * @param day the day containing relevant month and year information - * @return a label to display for the given month/year - */ - CharSequence format(CalendarDay day); + /** + * Converts the supplied day to a suitable month/year title + * + * @param day the day containing relevant month and year information + * @return a label to display for the given month/year + */ + CharSequence format(CalendarDay day); } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/format/WeekDayFormatter.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/format/WeekDayFormatter.java index 6322369b..0546ed3b 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/format/WeekDayFormatter.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/format/WeekDayFormatter.java @@ -6,16 +6,16 @@ * Supply labels for a given day of the week. */ public interface WeekDayFormatter { - /** - * Convert a given day of the week into a label. - * - * @param dayOfWeek the day of the week as returned by {@linkplain DayOfWeek#getValue()}. - * @return a label for the day of week. - */ - CharSequence format(DayOfWeek dayOfWeek); + /** + * Convert a given day of the week into a label. + * + * @param dayOfWeek the day of the week as returned by {@linkplain DayOfWeek#getValue()}. + * @return a label for the day of week. + */ + CharSequence format(DayOfWeek dayOfWeek); - /** - * Default implementation used by {@linkplain com.prolificinteractive.materialcalendarview.MaterialCalendarView} - */ - WeekDayFormatter DEFAULT = new CalendarWeekDayFormatter(); + /** + * Default implementation used by {@linkplain com.prolificinteractive.materialcalendarview.MaterialCalendarView} + */ + WeekDayFormatter DEFAULT = new CalendarWeekDayFormatter(); } diff --git a/library/src/main/java/com/prolificinteractive/materialcalendarview/spans/DotSpan.java b/library/src/main/java/com/prolificinteractive/materialcalendarview/spans/DotSpan.java index 421f10f5..f1a78d50 100644 --- a/library/src/main/java/com/prolificinteractive/materialcalendarview/spans/DotSpan.java +++ b/library/src/main/java/com/prolificinteractive/materialcalendarview/spans/DotSpan.java @@ -9,71 +9,71 @@ */ public class DotSpan implements LineBackgroundSpan { - /** - * Default radius used - */ - public static final float DEFAULT_RADIUS = 3; + /** + * Default radius used + */ + public static final float DEFAULT_RADIUS = 3; - private final float radius; - private final int color; + private final float radius; + private final int color; - /** - * Create a span to draw a dot using default radius and color - * - * @see #DotSpan(float, int) - * @see #DEFAULT_RADIUS - */ - public DotSpan() { - this.radius = DEFAULT_RADIUS; - this.color = 0; - } + /** + * Create a span to draw a dot using default radius and color + * + * @see #DotSpan(float, int) + * @see #DEFAULT_RADIUS + */ + public DotSpan() { + this.radius = DEFAULT_RADIUS; + this.color = 0; + } - /** - * Create a span to draw a dot using a specified color - * - * @param color color of the dot - * @see #DotSpan(float, int) - * @see #DEFAULT_RADIUS - */ - public DotSpan(int color) { - this.radius = DEFAULT_RADIUS; - this.color = color; - } + /** + * Create a span to draw a dot using a specified color + * + * @param color color of the dot + * @see #DotSpan(float, int) + * @see #DEFAULT_RADIUS + */ + public DotSpan(int color) { + this.radius = DEFAULT_RADIUS; + this.color = color; + } - /** - * Create a span to draw a dot using a specified radius - * - * @param radius radius for the dot - * @see #DotSpan(float, int) - */ - public DotSpan(float radius) { - this.radius = radius; - this.color = 0; - } + /** + * Create a span to draw a dot using a specified radius + * + * @param radius radius for the dot + * @see #DotSpan(float, int) + */ + public DotSpan(float radius) { + this.radius = radius; + this.color = 0; + } - /** - * Create a span to draw a dot using a specified radius and color - * - * @param radius radius for the dot - * @param color color of the dot - */ - public DotSpan(float radius, int color) { - this.radius = radius; - this.color = color; - } + /** + * Create a span to draw a dot using a specified radius and color + * + * @param radius radius for the dot + * @param color color of the dot + */ + public DotSpan(float radius, int color) { + this.radius = radius; + this.color = color; + } - @Override - public void drawBackground( - Canvas canvas, Paint paint, - int left, int right, int top, int baseline, int bottom, - CharSequence charSequence, - int start, int end, int lineNum - ) { - int oldColor = paint.getColor(); - if (color != 0) { - paint.setColor(color); - } - canvas.drawCircle((left + right) / 2, bottom + radius, radius, paint); - paint.setColor(oldColor); + @Override + public void drawBackground( + Canvas canvas, Paint paint, + int left, int right, int top, int baseline, int bottom, + CharSequence charSequence, + int start, int end, int lineNum + ) { + int oldColor = paint.getColor(); + if (color != 0) { + paint.setColor(color); } + canvas.drawCircle((left + right) / 2, bottom + radius, radius, paint); + paint.setColor(oldColor); + } } diff --git a/library/src/main/res/color/mcv_text_date_dark.xml b/library/src/main/res/color/mcv_text_date_dark.xml index 1b177125..a7d96ea0 100644 --- a/library/src/main/res/color/mcv_text_date_dark.xml +++ b/library/src/main/res/color/mcv_text_date_dark.xml @@ -3,16 +3,13 @@ android:enterFadeDuration="@android:integer/config_shortAnimTime" android:exitFadeDuration="@android:integer/config_shortAnimTime"> - + - + - + - + diff --git a/library/src/main/res/color/mcv_text_date_light.xml b/library/src/main/res/color/mcv_text_date_light.xml index 37521e4e..48c42272 100644 --- a/library/src/main/res/color/mcv_text_date_light.xml +++ b/library/src/main/res/color/mcv_text_date_light.xml @@ -3,16 +3,13 @@ android:enterFadeDuration="@android:integer/config_shortAnimTime" android:exitFadeDuration="@android:integer/config_shortAnimTime"> - + - + - + - + diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml index 977f6799..4946d70a 100644 --- a/library/src/main/res/values/attrs.xml +++ b/library/src/main/res/values/attrs.xml @@ -1,71 +1,71 @@ - + - - - + + + - - - - + + + + - - - - - - - - + + + + + + + + - - + + - - + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + diff --git a/library/src/main/res/values/ids.xml b/library/src/main/res/values/ids.xml index e730c3de..cb6dcb22 100644 --- a/library/src/main/res/values/ids.xml +++ b/library/src/main/res/values/ids.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/library/src/main/res/values/strings.xml b/library/src/main/res/values/strings.xml index 549c67f7..05a93ca3 100644 --- a/library/src/main/res/values/strings.xml +++ b/library/src/main/res/values/strings.xml @@ -1,6 +1,6 @@ - Go to previous - Go to next - Calendar + Go to previous + Go to next + Calendar diff --git a/library/src/main/res/values/styles.xml b/library/src/main/res/values/styles.xml index 63cc1ee1..70c5be03 100644 --- a/library/src/main/res/values/styles.xml +++ b/library/src/main/res/values/styles.xml @@ -1,20 +1,20 @@ - + - + - + \ No newline at end of file diff --git a/library/src/test/java/com/prolificinteractive/materialcalendarview/MonthlyRangeIndexTest.java b/library/src/test/java/com/prolificinteractive/materialcalendarview/MonthlyRangeIndexTest.java index 7b25fada..ceb160ff 100644 --- a/library/src/test/java/com/prolificinteractive/materialcalendarview/MonthlyRangeIndexTest.java +++ b/library/src/test/java/com/prolificinteractive/materialcalendarview/MonthlyRangeIndexTest.java @@ -4,7 +4,15 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; -import static org.threeten.bp.Month.*; +import static org.threeten.bp.Month.APRIL; +import static org.threeten.bp.Month.DECEMBER; +import static org.threeten.bp.Month.FEBRUARY; +import static org.threeten.bp.Month.JANUARY; +import static org.threeten.bp.Month.JULY; +import static org.threeten.bp.Month.JUNE; +import static org.threeten.bp.Month.MAY; +import static org.threeten.bp.Month.NOVEMBER; +import static org.threeten.bp.Month.OCTOBER; public class MonthlyRangeIndexTest { diff --git a/library/src/test/java/com/prolificinteractive/materialcalendarview/WeeklyRangeIndexTest.java b/library/src/test/java/com/prolificinteractive/materialcalendarview/WeeklyRangeIndexTest.java index 7c4c2f54..2afdc5fd 100644 --- a/library/src/test/java/com/prolificinteractive/materialcalendarview/WeeklyRangeIndexTest.java +++ b/library/src/test/java/com/prolificinteractive/materialcalendarview/WeeklyRangeIndexTest.java @@ -4,8 +4,17 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; -import static org.threeten.bp.DayOfWeek.*; -import static org.threeten.bp.Month.*; +import static org.threeten.bp.DayOfWeek.FRIDAY; +import static org.threeten.bp.DayOfWeek.MONDAY; +import static org.threeten.bp.DayOfWeek.SATURDAY; +import static org.threeten.bp.DayOfWeek.SUNDAY; +import static org.threeten.bp.DayOfWeek.THURSDAY; +import static org.threeten.bp.DayOfWeek.TUESDAY; +import static org.threeten.bp.DayOfWeek.WEDNESDAY; +import static org.threeten.bp.Month.DECEMBER; +import static org.threeten.bp.Month.FEBRUARY; +import static org.threeten.bp.Month.JANUARY; +import static org.threeten.bp.Month.MARCH; public class WeeklyRangeIndexTest { private static final int _2018 = 2018; diff --git a/library/src/test/java/com/prolificinteractive/materialcalendarview/format/CalendarWeekDayFormatterTest.java b/library/src/test/java/com/prolificinteractive/materialcalendarview/format/CalendarWeekDayFormatterTest.java index 646a06a7..132db575 100644 --- a/library/src/test/java/com/prolificinteractive/materialcalendarview/format/CalendarWeekDayFormatterTest.java +++ b/library/src/test/java/com/prolificinteractive/materialcalendarview/format/CalendarWeekDayFormatterTest.java @@ -1,64 +1,54 @@ package com.prolificinteractive.materialcalendarview.format; +import java.util.Locale; import org.junit.After; import org.junit.Before; import org.junit.Test; - -import java.util.Locale; import org.threeten.bp.DayOfWeek; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.*; +import static org.junit.Assert.assertThat; public class CalendarWeekDayFormatterTest { - public CalendarWeekDayFormatter formatter; - public Locale defaultLocaleOriginal; + public CalendarWeekDayFormatter formatter; + public Locale defaultLocaleOriginal; - @Before - public void setUp() throws Exception { - defaultLocaleOriginal = Locale.getDefault(); - Locale.setDefault(Locale.ENGLISH); - formatter = new CalendarWeekDayFormatter(); - } + @Before public void setUp() { + defaultLocaleOriginal = Locale.getDefault(); + Locale.setDefault(Locale.ENGLISH); + formatter = new CalendarWeekDayFormatter(); + } - @After - public void tearDown() throws Exception { - Locale.setDefault(defaultLocaleOriginal); - } + @After public void tearDown() { + Locale.setDefault(defaultLocaleOriginal); + } - @Test - public void testFormattedDayOfWeek_Sunday() throws Exception { - assertThat(formatter.format(DayOfWeek.SUNDAY).toString(), is("Sun")); - } + @Test public void testFormattedDayOfWeek_Sunday() { + assertThat(formatter.format(DayOfWeek.SUNDAY).toString(), is("Sun")); + } - @Test - public void testFormattedDayOfWeek_Monday() throws Exception { - assertThat(formatter.format(DayOfWeek.MONDAY).toString(), is("Mon")); - } + @Test public void testFormattedDayOfWeek_Monday() { + assertThat(formatter.format(DayOfWeek.MONDAY).toString(), is("Mon")); + } - @Test - public void testFormattedDayOfWeek_Tuesday() throws Exception { - assertThat(formatter.format(DayOfWeek.TUESDAY).toString(), is("Tue")); - } + @Test public void testFormattedDayOfWeek_Tuesday() { + assertThat(formatter.format(DayOfWeek.TUESDAY).toString(), is("Tue")); + } - @Test - public void testFormattedDayOfWeek_Wednesday() throws Exception { - assertThat(formatter.format(DayOfWeek.WEDNESDAY).toString(), is("Wed")); - } + @Test public void testFormattedDayOfWeek_Wednesday() { + assertThat(formatter.format(DayOfWeek.WEDNESDAY).toString(), is("Wed")); + } - @Test - public void testFormattedDayOfWeek_Thursday() throws Exception { - assertThat(formatter.format(DayOfWeek.THURSDAY).toString(), is("Thu")); - } + @Test public void testFormattedDayOfWeek_Thursday() { + assertThat(formatter.format(DayOfWeek.THURSDAY).toString(), is("Thu")); + } - @Test - public void testFormattedDayOfWeek_Friday() throws Exception { - assertThat(formatter.format(DayOfWeek.FRIDAY).toString(), is("Fri")); - } + @Test public void testFormattedDayOfWeek_Friday() { + assertThat(formatter.format(DayOfWeek.FRIDAY).toString(), is("Fri")); + } - @Test - public void shouldReturnCorrectFormattedEnglishTextOfSaturday() throws Exception { - assertThat(formatter.format(DayOfWeek.SATURDAY).toString(), is("Sat")); - } + @Test public void shouldReturnCorrectFormattedEnglishTextOfSaturday() { + assertThat(formatter.format(DayOfWeek.SATURDAY).toString(), is("Sat")); + } } \ No newline at end of file diff --git a/sample/build.gradle b/sample/build.gradle index 76cd7adf..01c0408f 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -1,37 +1,37 @@ apply plugin: 'com.android.application' android { - compileSdkVersion rootProject.ext.compileSdkVersion + compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "com.prolificinteractive.materialcalendarview.sample" + defaultConfig { + applicationId "com.prolificinteractive.materialcalendarview.sample" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - } + versionCode 1 + versionName "1.0" + } - lintOptions { - abortOnError false - } + lintOptions { + abortOnError false + } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } } dependencies { - // You should use the commented out line below in you're application. - // We depend on the source directly here so that development is easier. - implementation project(':library') - //compile 'com.prolificinteractive:material-calendarview:1.4.3' - - implementation rootProject.ext.threeTenAbp - implementation rootProject.ext.supportAppCompat - implementation rootProject.ext.recyclerviewV7 - implementation rootProject.ext.butterknife - annotationProcessor rootProject.ext.butterknifeCompiler + // You should use the commented out line below in you're application. + // We depend on the source directly here so that development is easier. + implementation project(':library') + //compile 'com.prolificinteractive:material-calendarview:1.4.3' + + implementation rootProject.ext.threeTenAbp + implementation rootProject.ext.supportAppCompat + implementation rootProject.ext.recyclerviewV7 + implementation rootProject.ext.butterknife + annotationProcessor rootProject.ext.butterknifeCompiler } diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index e05353b7..6dedbeb8 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -3,256 +3,256 @@ package="com.prolificinteractive.materialcalendarview.sample" > - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/BasicActivity.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/BasicActivity.java index d18d26ed..e3168c13 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/BasicActivity.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/BasicActivity.java @@ -5,52 +5,60 @@ import android.support.v7.app.AppCompatActivity; import android.widget.TextView; import android.widget.Toast; -import com.prolificinteractive.materialcalendarview.*; import butterknife.BindView; import butterknife.ButterKnife; +import com.prolificinteractive.materialcalendarview.CalendarDay; +import com.prolificinteractive.materialcalendarview.MaterialCalendarView; +import com.prolificinteractive.materialcalendarview.OnDateLongClickListener; +import com.prolificinteractive.materialcalendarview.OnDateSelectedListener; +import com.prolificinteractive.materialcalendarview.OnMonthChangedListener; import org.threeten.bp.format.DateTimeFormatter; /** * Shows off the most basic usage */ -public class BasicActivity extends AppCompatActivity implements OnDateSelectedListener, OnMonthChangedListener, OnDateLongClickListener { - - private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("EEE, d MMM yyyy"); - - @BindView(R.id.calendarView) - MaterialCalendarView widget; - - @BindView(R.id.textView) - TextView textView; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_basic); - ButterKnife.bind(this); - - widget.setOnDateChangedListener(this); - widget.setOnDateLongClickListener(this); - widget.setOnMonthChangedListener(this); - - //Setup initial text - textView.setText("No Selection"); - } - - @Override - public void onDateSelected(@NonNull MaterialCalendarView widget, @NonNull CalendarDay date, boolean selected) { - textView.setText(selected ? FORMATTER.format(date.getDate()) : "No Selection"); - } - - @Override - public void onDateLongClick(@NonNull MaterialCalendarView widget, @NonNull CalendarDay date) { - final String text = String.format("%s is available", FORMATTER.format(date.getDate())); - Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); - } - - @Override - public void onMonthChanged(MaterialCalendarView widget, CalendarDay date) { - //noinspection ConstantConditions - getSupportActionBar().setTitle(FORMATTER.format(date.getDate())); - } +public class BasicActivity extends AppCompatActivity + implements OnDateSelectedListener, OnMonthChangedListener, OnDateLongClickListener { + + private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("EEE, d MMM yyyy"); + + @BindView(R.id.calendarView) + MaterialCalendarView widget; + + @BindView(R.id.textView) + TextView textView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_basic); + ButterKnife.bind(this); + + widget.setOnDateChangedListener(this); + widget.setOnDateLongClickListener(this); + widget.setOnMonthChangedListener(this); + + //Setup initial text + textView.setText("No Selection"); + } + + @Override + public void onDateSelected( + @NonNull MaterialCalendarView widget, + @NonNull CalendarDay date, + boolean selected) { + textView.setText(selected ? FORMATTER.format(date.getDate()) : "No Selection"); + } + + @Override + public void onDateLongClick(@NonNull MaterialCalendarView widget, @NonNull CalendarDay date) { + final String text = String.format("%s is available", FORMATTER.format(date.getDate())); + Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); + } + + @Override + public void onMonthChanged(MaterialCalendarView widget, CalendarDay date) { + //noinspection ConstantConditions + getSupportActionBar().setTitle(FORMATTER.format(date.getDate())); + } } diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/BasicActivityDecorated.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/BasicActivityDecorated.java index 7fe46aea..d67a5b8b 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/BasicActivityDecorated.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/BasicActivityDecorated.java @@ -5,7 +5,8 @@ import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; - +import butterknife.BindView; +import butterknife.ButterKnife; import com.prolificinteractive.materialcalendarview.CalendarDay; import com.prolificinteractive.materialcalendarview.MaterialCalendarView; import com.prolificinteractive.materialcalendarview.OnDateSelectedListener; @@ -13,13 +14,9 @@ import com.prolificinteractive.materialcalendarview.sample.decorators.HighlightWeekendsDecorator; import com.prolificinteractive.materialcalendarview.sample.decorators.MySelectorDecorator; import com.prolificinteractive.materialcalendarview.sample.decorators.OneDayDecorator; - import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executors; - -import butterknife.BindView; -import butterknife.ButterKnife; import org.threeten.bp.LocalDate; import org.threeten.bp.Month; @@ -28,76 +25,79 @@ */ public class BasicActivityDecorated extends AppCompatActivity implements OnDateSelectedListener { - private final OneDayDecorator oneDayDecorator = new OneDayDecorator(); + private final OneDayDecorator oneDayDecorator = new OneDayDecorator(); - @BindView(R.id.calendarView) - MaterialCalendarView widget; + @BindView(R.id.calendarView) + MaterialCalendarView widget; - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_basic); - ButterKnife.bind(this); + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_basic); + ButterKnife.bind(this); - widget.setOnDateChangedListener(this); - widget.setShowOtherDates(MaterialCalendarView.SHOW_ALL); + widget.setOnDateChangedListener(this); + widget.setShowOtherDates(MaterialCalendarView.SHOW_ALL); - final LocalDate instance = LocalDate.now(); - widget.setSelectedDate(instance); + final LocalDate instance = LocalDate.now(); + widget.setSelectedDate(instance); - final LocalDate min = LocalDate.of(instance.getYear(), Month.JANUARY, 1); - final LocalDate max = LocalDate.of(instance.getYear(), Month.DECEMBER, 31); + final LocalDate min = LocalDate.of(instance.getYear(), Month.JANUARY, 1); + final LocalDate max = LocalDate.of(instance.getYear(), Month.DECEMBER, 31); - widget.state().edit().setMinimumDate(min).setMaximumDate(max).commit(); + widget.state().edit().setMinimumDate(min).setMaximumDate(max).commit(); - widget.addDecorators( - new MySelectorDecorator(this), - new HighlightWeekendsDecorator(), - oneDayDecorator - ); + widget.addDecorators( + new MySelectorDecorator(this), + new HighlightWeekendsDecorator(), + oneDayDecorator + ); - new ApiSimulator().executeOnExecutor(Executors.newSingleThreadExecutor()); - } + new ApiSimulator().executeOnExecutor(Executors.newSingleThreadExecutor()); + } + + @Override + public void onDateSelected( + @NonNull MaterialCalendarView widget, + @NonNull CalendarDay date, + boolean selected) { + //If you change a decorate, you need to invalidate decorators + oneDayDecorator.setDate(date.getDate()); + widget.invalidateDecorators(); + } + + /** + * Simulate an API call to show how to add decorators + */ + private class ApiSimulator extends AsyncTask> { @Override - public void onDateSelected(@NonNull MaterialCalendarView widget, @NonNull CalendarDay date, boolean selected) { - //If you change a decorate, you need to invalidate decorators - oneDayDecorator.setDate(date.getDate()); - widget.invalidateDecorators(); + protected List doInBackground(@NonNull Void... voids) { + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + LocalDate temp = LocalDate.now().minusMonths(2); + final ArrayList dates = new ArrayList<>(); + for (int i = 0; i < 30; i++) { + final CalendarDay day = CalendarDay.from(temp); + dates.add(day); + temp = temp.plusDays(5); + } + + return dates; } - /** - * Simulate an API call to show how to add decorators - */ - private class ApiSimulator extends AsyncTask> { - - @Override - protected List doInBackground(@NonNull Void... voids) { - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - LocalDate temp = LocalDate.now().minusMonths(2); - final ArrayList dates = new ArrayList<>(); - for (int i = 0; i < 30; i++) { - final CalendarDay day = CalendarDay.from(temp); - dates.add(day); - temp = temp.plusDays(5); - } - - return dates; - } - - @Override - protected void onPostExecute(@NonNull List calendarDays) { - super.onPostExecute(calendarDays); - - if (isFinishing()) { - return; - } - - widget.addDecorator(new EventDecorator(Color.RED, calendarDays)); - } + @Override + protected void onPostExecute(@NonNull List calendarDays) { + super.onPostExecute(calendarDays); + + if (isFinishing()) { + return; + } + + widget.addDecorator(new EventDecorator(Color.RED, calendarDays)); } + } } diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/CustomTileDimensions.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/CustomTileDimensions.java index 1aac9ab7..8d60de5e 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/CustomTileDimensions.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/CustomTileDimensions.java @@ -8,16 +8,14 @@ import android.support.v7.app.AppCompatActivity; import android.widget.LinearLayout; import android.widget.NumberPicker; - +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; import com.prolificinteractive.materialcalendarview.CalendarDay; import com.prolificinteractive.materialcalendarview.DayViewDecorator; import com.prolificinteractive.materialcalendarview.DayViewFacade; import com.prolificinteractive.materialcalendarview.MaterialCalendarView; -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; - /** * Created by maragues on 17/06/16. */ @@ -64,15 +62,15 @@ public void onWidthClick() { view.setWrapSelectorWheel(false); view.setValue(currentTileWidth); new AlertDialog.Builder(this) - .setView(view) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(@NonNull DialogInterface dialog, int which) { - currentTileWidth = view.getValue(); - widget.setTileWidthDp(currentTileWidth); - } - }) - .show(); + .setView(view) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(@NonNull DialogInterface dialog, int which) { + currentTileWidth = view.getValue(); + widget.setTileWidthDp(currentTileWidth); + } + }) + .show(); } @OnClick(R.id.custom_tile_height_size) @@ -83,15 +81,15 @@ public void onHeightClick() { view.setWrapSelectorWheel(false); view.setValue(currentTileHeight); new AlertDialog.Builder(this) - .setView(view) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(@NonNull DialogInterface dialog, int which) { - currentTileHeight = view.getValue(); - widget.setTileHeightDp(currentTileHeight); - } - }) - .show(); + .setView(view) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(@NonNull DialogInterface dialog, int which) { + currentTileHeight = view.getValue(); + widget.setTileHeightDp(currentTileHeight); + } + }) + .show(); } private class TodayDecorator implements DayViewDecorator { diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/CustomizeCodeActivity.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/CustomizeCodeActivity.java index 33d991db..3bf897b2 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/CustomizeCodeActivity.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/CustomizeCodeActivity.java @@ -3,52 +3,52 @@ import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.TypedValue; - +import butterknife.BindView; +import butterknife.ButterKnife; import com.prolificinteractive.materialcalendarview.CalendarDay; import com.prolificinteractive.materialcalendarview.CalendarMode; import com.prolificinteractive.materialcalendarview.MaterialCalendarView; import com.prolificinteractive.materialcalendarview.format.ArrayWeekDayFormatter; import com.prolificinteractive.materialcalendarview.format.MonthArrayTitleFormatter; - -import butterknife.BindView; -import butterknife.ButterKnife; import org.threeten.bp.DayOfWeek; public class CustomizeCodeActivity extends AppCompatActivity { - @BindView(R.id.calendarView) - MaterialCalendarView widget; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_basic); - ButterKnife.bind(this); - - widget.setShowOtherDates(MaterialCalendarView.SHOW_ALL); - widget.setArrowColor(getResources().getColor(R.color.sample_primary)); - widget.setLeftArrowMask(getResources().getDrawable(R.drawable.ic_navigation_arrow_back)); - widget.setRightArrowMask(getResources().getDrawable(R.drawable.ic_navigation_arrow_forward)); - widget.setSelectionColor(getResources().getColor(R.color.sample_primary)); - widget.setWeekDayTextAppearance(R.style.CustomTextAppearance); - widget.setHeaderTextAppearance(R.style.CustomTextAppearance); - widget.setDateTextAppearance(R.style.CustomTextAppearance); - widget.setTitleFormatter(new MonthArrayTitleFormatter(getResources().getTextArray(R.array.custom_months))); - widget.setWeekDayFormatter(new ArrayWeekDayFormatter(getResources().getTextArray(R.array.custom_weekdays))); - widget.setTileSize((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 36, getResources().getDisplayMetrics())); - widget.setTitleAnimationOrientation(MaterialCalendarView.VERTICAL); - - CalendarDay today = CalendarDay.from(2016, 5, 2); - widget.setCurrentDate(today); - widget.setSelectedDate(today); - - widget.state().edit() - .setFirstDayOfWeek(DayOfWeek.WEDNESDAY) - .setMinimumDate(CalendarDay.from(2016, 4, 3)) - .setMaximumDate(CalendarDay.from(2016, 5, 12)) - .setCalendarDisplayMode(CalendarMode.WEEKS) - .commit(); - - } - + @BindView(R.id.calendarView) + MaterialCalendarView widget; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_basic); + ButterKnife.bind(this); + + widget.setShowOtherDates(MaterialCalendarView.SHOW_ALL); + widget.setArrowColor(getResources().getColor(R.color.sample_primary)); + widget.setLeftArrowMask(getResources().getDrawable(R.drawable.ic_navigation_arrow_back)); + widget.setRightArrowMask(getResources().getDrawable(R.drawable.ic_navigation_arrow_forward)); + widget.setSelectionColor(getResources().getColor(R.color.sample_primary)); + widget.setWeekDayTextAppearance(R.style.CustomTextAppearance); + widget.setHeaderTextAppearance(R.style.CustomTextAppearance); + widget.setDateTextAppearance(R.style.CustomTextAppearance); + widget.setTitleFormatter(new MonthArrayTitleFormatter(getResources().getTextArray(R.array.custom_months))); + widget.setWeekDayFormatter(new ArrayWeekDayFormatter(getResources().getTextArray(R.array.custom_weekdays))); + widget.setTileSize((int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + 36, + getResources().getDisplayMetrics() + )); + widget.setTitleAnimationOrientation(MaterialCalendarView.VERTICAL); + + CalendarDay today = CalendarDay.from(2016, 5, 2); + widget.setCurrentDate(today); + widget.setSelectedDate(today); + + widget.state().edit() + .setFirstDayOfWeek(DayOfWeek.WEDNESDAY) + .setMinimumDate(CalendarDay.from(2016, 4, 3)) + .setMaximumDate(CalendarDay.from(2016, 5, 12)) + .setCalendarDisplayMode(CalendarMode.WEEKS) + .commit(); + } } diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/CustomizeXmlActivity.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/CustomizeXmlActivity.java index 526b6d5a..baf33683 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/CustomizeXmlActivity.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/CustomizeXmlActivity.java @@ -2,22 +2,19 @@ import android.os.Bundle; import android.support.v7.app.AppCompatActivity; - -import com.prolificinteractive.materialcalendarview.MaterialCalendarView; - import butterknife.BindView; import butterknife.ButterKnife; +import com.prolificinteractive.materialcalendarview.MaterialCalendarView; public class CustomizeXmlActivity extends AppCompatActivity { - @BindView(R.id.calendarView) - MaterialCalendarView widget; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_customization); - ButterKnife.bind(this); - } + @BindView(R.id.calendarView) + MaterialCalendarView widget; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_customization); + ButterKnife.bind(this); + } } diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/DialogsActivity.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/DialogsActivity.java index d32a30de..befb6ef9 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/DialogsActivity.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/DialogsActivity.java @@ -9,11 +9,11 @@ import android.view.LayoutInflater; import android.view.View; import android.widget.TextView; +import butterknife.ButterKnife; +import butterknife.OnClick; import com.prolificinteractive.materialcalendarview.CalendarDay; import com.prolificinteractive.materialcalendarview.MaterialCalendarView; import com.prolificinteractive.materialcalendarview.OnDateSelectedListener; -import butterknife.ButterKnife; -import butterknife.OnClick; import org.threeten.bp.format.DateTimeFormatter; /** @@ -21,67 +21,71 @@ */ public class DialogsActivity extends AppCompatActivity { - private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("EEE, d MMM yyyy"); + private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("EEE, d MMM yyyy"); - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_dialogs); - ButterKnife.bind(this); - } + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_dialogs); + ButterKnife.bind(this); + } - @OnClick(R.id.button_normal_dialog) - void onNormalDialogClick() { - new SimpleDialogFragment().show(getSupportFragmentManager(), "test-normal"); - } + @OnClick(R.id.button_normal_dialog) + void onNormalDialogClick() { + new SimpleDialogFragment().show(getSupportFragmentManager(), "test-normal"); + } - @OnClick(R.id.button_simple_dialog) - void onSimpleCalendarDialogClick() { - new SimpleCalendarDialogFragment().show(getSupportFragmentManager(), "test-simple-calendar"); - } + @OnClick(R.id.button_simple_dialog) + void onSimpleCalendarDialogClick() { + new SimpleCalendarDialogFragment().show(getSupportFragmentManager(), "test-simple-calendar"); + } + + public static class SimpleDialogFragment extends AppCompatDialogFragment { - public static class SimpleDialogFragment extends AppCompatDialogFragment { - - @NonNull - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - return new AlertDialog.Builder(getActivity()) - .setTitle(R.string.title_activity_dialogs) - .setMessage("Test Dialog") - .setPositiveButton(android.R.string.ok, null) - .create(); - } + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + return new AlertDialog.Builder(getActivity()) + .setTitle(R.string.title_activity_dialogs) + .setMessage("Test Dialog") + .setPositiveButton(android.R.string.ok, null) + .create(); } + } - public static class SimpleCalendarDialogFragment extends AppCompatDialogFragment implements OnDateSelectedListener { + public static class SimpleCalendarDialogFragment extends AppCompatDialogFragment + implements OnDateSelectedListener { - private TextView textView; + private TextView textView; - @NonNull - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - LayoutInflater inflater = getActivity().getLayoutInflater(); + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + LayoutInflater inflater = getActivity().getLayoutInflater(); - //inflate custom layout and get views - //pass null as parent view because will be in dialog layout - View view = inflater.inflate(R.layout.dialog_basic, null); + //inflate custom layout and get views + //pass null as parent view because will be in dialog layout + View view = inflater.inflate(R.layout.dialog_basic, null); - textView = view.findViewById(R.id.textView); + textView = view.findViewById(R.id.textView); - MaterialCalendarView widget = view.findViewById(R.id.calendarView); + MaterialCalendarView widget = view.findViewById(R.id.calendarView); - widget.setOnDateChangedListener(this); + widget.setOnDateChangedListener(this); - return new AlertDialog.Builder(getActivity()) - .setTitle(R.string.title_activity_dialogs) - .setView(view) - .setPositiveButton(android.R.string.ok, null) - .create(); - } + return new AlertDialog.Builder(getActivity()) + .setTitle(R.string.title_activity_dialogs) + .setView(view) + .setPositiveButton(android.R.string.ok, null) + .create(); + } - @Override - public void onDateSelected(@NonNull MaterialCalendarView widget, @NonNull CalendarDay date, boolean selected) { - textView.setText(FORMATTER.format(date.getDate())); - } + @Override + public void onDateSelected( + @NonNull MaterialCalendarView widget, + @NonNull CalendarDay date, + boolean selected) { + textView.setText(FORMATTER.format(date.getDate())); } + } } diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/DisableDaysActivity.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/DisableDaysActivity.java index efc98445..d164553b 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/DisableDaysActivity.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/DisableDaysActivity.java @@ -2,14 +2,12 @@ import android.os.Bundle; import android.support.v7.app.AppCompatActivity; - +import butterknife.BindView; +import butterknife.ButterKnife; import com.prolificinteractive.materialcalendarview.CalendarDay; import com.prolificinteractive.materialcalendarview.DayViewDecorator; import com.prolificinteractive.materialcalendarview.DayViewFacade; import com.prolificinteractive.materialcalendarview.MaterialCalendarView; - -import butterknife.BindView; -import butterknife.ButterKnife; import org.threeten.bp.LocalDate; import org.threeten.bp.Month; @@ -18,90 +16,90 @@ */ public class DisableDaysActivity extends AppCompatActivity { - @BindView(R.id.calendarView) MaterialCalendarView widget; + @BindView(R.id.calendarView) MaterialCalendarView widget; - @Override protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_basic); - ButterKnife.bind(this); + @Override protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_basic); + ButterKnife.bind(this); - // Add a decorator to disable prime numbered days - widget.addDecorator(new PrimeDayDisableDecorator()); - // Add a second decorator that explicitly enables days <= 10. This will work because - // decorators are applied in order, and the system allows re-enabling - widget.addDecorator(new EnableOneToTenDecorator()); + // Add a decorator to disable prime numbered days + widget.addDecorator(new PrimeDayDisableDecorator()); + // Add a second decorator that explicitly enables days <= 10. This will work because + // decorators are applied in order, and the system allows re-enabling + widget.addDecorator(new EnableOneToTenDecorator()); - final LocalDate calendar = LocalDate.now(); - widget.setSelectedDate(calendar); + final LocalDate calendar = LocalDate.now(); + widget.setSelectedDate(calendar); - final LocalDate min = LocalDate.of(calendar.getYear(), Month.JANUARY, 1); - final LocalDate max = LocalDate.of(calendar.getYear() + 1, Month.OCTOBER, 31); + final LocalDate min = LocalDate.of(calendar.getYear(), Month.JANUARY, 1); + final LocalDate max = LocalDate.of(calendar.getYear() + 1, Month.OCTOBER, 31); - widget.state().edit() - .setMinimumDate(min) - .setMaximumDate(max) - .commit(); - } - - private static class PrimeDayDisableDecorator implements DayViewDecorator { - - @Override public boolean shouldDecorate(final CalendarDay day) { - return PRIME_TABLE[day.getDay()]; - } + widget.state().edit() + .setMinimumDate(min) + .setMaximumDate(max) + .commit(); + } - @Override public void decorate(final DayViewFacade view) { - view.setDaysDisabled(true); - } + private static class PrimeDayDisableDecorator implements DayViewDecorator { - private static boolean[] PRIME_TABLE = { - false, // 0? - false, - true, // 2 - true, // 3 - false, - true, // 5 - false, - true, // 7 - false, - false, - false, - true, // 11 - false, - true, // 13 - false, - false, - false, - true, // 17 - false, - true, // 19 - false, - false, - false, - true, // 23 - false, - false, - false, - false, - false, - true, // 29 - false, - true, // 31 - false, - false, - false, //PADDING - }; + @Override public boolean shouldDecorate(final CalendarDay day) { + return PRIME_TABLE[day.getDay()]; } - private static class EnableOneToTenDecorator implements DayViewDecorator { + @Override public void decorate(final DayViewFacade view) { + view.setDaysDisabled(true); + } - @Override - public boolean shouldDecorate(CalendarDay day) { - return day.getDay() <= 10; - } + private static boolean[] PRIME_TABLE = { + false, // 0? + false, + true, // 2 + true, // 3 + false, + true, // 5 + false, + true, // 7 + false, + false, + false, + true, // 11 + false, + true, // 13 + false, + false, + false, + true, // 17 + false, + true, // 19 + false, + false, + false, + true, // 23 + false, + false, + false, + false, + false, + true, // 29 + false, + true, // 31 + false, + false, + false, //PADDING + }; + } + + private static class EnableOneToTenDecorator implements DayViewDecorator { + + @Override + public boolean shouldDecorate(CalendarDay day) { + return day.getDay() <= 10; + } - @Override - public void decorate(DayViewFacade view) { - view.setDaysDisabled(false); - } + @Override + public void decorate(DayViewFacade view) { + view.setDaysDisabled(false); } + } } diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/DynamicSettersActivity.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/DynamicSettersActivity.java index 5a90a4af..f0f3c722 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/DynamicSettersActivity.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/DynamicSettersActivity.java @@ -4,335 +4,343 @@ import android.content.Context; import android.content.DialogInterface; import android.graphics.Color; -import android.icu.util.Calendar; import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; -import android.util.Log; import android.transition.TransitionManager; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; -import android.widget.DatePicker; import android.widget.LinearLayout; import android.widget.NumberPicker; import android.widget.Toast; -import com.prolificinteractive.materialcalendarview.CalendarDay; -import com.prolificinteractive.materialcalendarview.CalendarMode; -import com.prolificinteractive.materialcalendarview.MaterialCalendarView; -import java.util.Random; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnCheckedChanged; import butterknife.OnClick; +import com.prolificinteractive.materialcalendarview.CalendarDay; +import com.prolificinteractive.materialcalendarview.CalendarMode; +import com.prolificinteractive.materialcalendarview.MaterialCalendarView; import com.prolificinteractive.materialcalendarview.OnDateLongClickListener; +import java.util.Random; import org.threeten.bp.DayOfWeek; import org.threeten.bp.format.DateTimeFormatter; public class DynamicSettersActivity extends AppCompatActivity implements OnDateLongClickListener { - private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("EEE, d MMM yyyy"); - - @BindView(R.id.calendarView) MaterialCalendarView widget; - @BindView(R.id.animate_mode_transition) CheckBox animateModeTransition; - @BindView(R.id.parent) ViewGroup parent; - - private int currentTileSize; - private int currentTileWidth; - private int currentTileHeight; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_dynamic_setters); - ButterKnife.bind(this); - - currentTileSize = MaterialCalendarView.DEFAULT_TILE_SIZE_DP; - currentTileWidth = MaterialCalendarView.DEFAULT_TILE_SIZE_DP; - currentTileHeight = MaterialCalendarView.DEFAULT_TILE_SIZE_DP; + private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("EEE, d MMM yyyy"); + + @BindView(R.id.calendarView) MaterialCalendarView widget; + @BindView(R.id.animate_mode_transition) CheckBox animateModeTransition; + @BindView(R.id.parent) ViewGroup parent; + + private int currentTileSize; + private int currentTileWidth; + private int currentTileHeight; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_dynamic_setters); + ButterKnife.bind(this); + + currentTileSize = MaterialCalendarView.DEFAULT_TILE_SIZE_DP; + currentTileWidth = MaterialCalendarView.DEFAULT_TILE_SIZE_DP; + currentTileHeight = MaterialCalendarView.DEFAULT_TILE_SIZE_DP; + + widget.setOnTitleClickListener(new View.OnClickListener() { + @Override + public void onClick(final View view) { + Toast.makeText(DynamicSettersActivity.this, R.string.today, Toast.LENGTH_SHORT).show(); + } + }); + + widget.setOnDateLongClickListener(this); + } + + @OnClick(R.id.button_other_dates) + void onOtherDatesClicked() { + CharSequence[] items = { + "Other Months", + "Out Of Range", + "Decorated Disabled", + "Select days outside month" + }; + final int[] itemValues = { + MaterialCalendarView.SHOW_OTHER_MONTHS, + MaterialCalendarView.SHOW_OUT_OF_RANGE, + MaterialCalendarView.SHOW_DECORATED_DISABLED, + }; + int showOtherDates = widget.getShowOtherDates(); - widget.setOnTitleClickListener(new View.OnClickListener() { - @Override - public void onClick(final View view) { - Toast.makeText(DynamicSettersActivity.this, R.string.today, Toast.LENGTH_SHORT).show(); + boolean[] initSelections = { + MaterialCalendarView.showOtherMonths(showOtherDates), + MaterialCalendarView.showOutOfRange(showOtherDates), + MaterialCalendarView.showDecoratedDisabled(showOtherDates), + widget.allowClickDaysOutsideCurrentMonth() + }; + new AlertDialog.Builder(this) + .setTitle("Show Other Dates") + .setMultiChoiceItems( + items, + initSelections, + new DialogInterface.OnMultiChoiceClickListener() { + @Override + public void onClick(DialogInterface dialog, int which, boolean isChecked) { + if (which < 3) { + int showOtherDates = widget.getShowOtherDates(); + if (isChecked) { + //Set flag + showOtherDates |= itemValues[which]; + } else { + //Unset flag + showOtherDates &= ~itemValues[which]; + } + widget.setShowOtherDates(showOtherDates); + } else if (which == 3) { + widget.setAllowClickDaysOutsideCurrentMonth(isChecked); + } + } } - }); - - widget.setOnDateLongClickListener(this); + ) + .setPositiveButton(android.R.string.ok, null) + .show(); + } + + @OnCheckedChanged(R.id.enable_save_current_position) + void onSaveCurrentPositionChecked(boolean checked) { + widget.state().edit().isCacheCalendarPositionEnabled(checked).commit(); + } + + @OnCheckedChanged(R.id.show_week_days) + void onShowWeekDaysChecked(boolean checked) { + widget.state().edit().setShowWeekDays(checked).commit(); + } + + @OnCheckedChanged(R.id.check_text_appearance) + void onTextAppearanceChecked(boolean checked) { + if (checked) { + widget.setHeaderTextAppearance(R.style.TextAppearance_AppCompat_Large); + widget.setDateTextAppearance(R.style.TextAppearance_AppCompat_Medium); + widget.setWeekDayTextAppearance(R.style.TextAppearance_AppCompat_Medium); + } else { + widget.setHeaderTextAppearance(R.style.TextAppearance_MaterialCalendarWidget_Header); + widget.setDateTextAppearance(R.style.TextAppearance_MaterialCalendarWidget_Date); + widget.setWeekDayTextAppearance(R.style.TextAppearance_MaterialCalendarWidget_WeekDay); } - - @OnClick(R.id.button_other_dates) - void onOtherDatesClicked() { - CharSequence[] items = { - "Other Months", - "Out Of Range", - "Decorated Disabled", - "Select days outside month" - }; - final int[] itemValues = { - MaterialCalendarView.SHOW_OTHER_MONTHS, - MaterialCalendarView.SHOW_OUT_OF_RANGE, - MaterialCalendarView.SHOW_DECORATED_DISABLED, - }; - int showOtherDates = widget.getShowOtherDates(); - - boolean[] initSelections = { - MaterialCalendarView.showOtherMonths(showOtherDates), - MaterialCalendarView.showOutOfRange(showOtherDates), - MaterialCalendarView.showDecoratedDisabled(showOtherDates), - widget.allowClickDaysOutsideCurrentMonth() - }; - new AlertDialog.Builder(this) - .setTitle("Show Other Dates") - .setMultiChoiceItems(items, initSelections, new DialogInterface.OnMultiChoiceClickListener() { - @Override - public void onClick(DialogInterface dialog, int which, boolean isChecked) { - if (which < 3) { - int showOtherDates = widget.getShowOtherDates(); - if (isChecked) { - //Set flag - showOtherDates |= itemValues[which]; - } else { - //Unset flag - showOtherDates &= ~itemValues[which]; - } - widget.setShowOtherDates(showOtherDates); - } else if (which == 3) { - widget.setAllowClickDaysOutsideCurrentMonth(isChecked); - } - } - }) - .setPositiveButton(android.R.string.ok, null) - .show(); - } - - @OnCheckedChanged(R.id.enable_save_current_position) - void onSaveCurrentPositionChecked(boolean checked) { - widget.state().edit().isCacheCalendarPositionEnabled(checked).commit(); - } - - @OnCheckedChanged(R.id.show_week_days) - void onShowWeekDaysChecked(boolean checked) { - widget.state().edit().setShowWeekDays(checked).commit(); - } - - @OnCheckedChanged(R.id.check_text_appearance) - void onTextAppearanceChecked(boolean checked) { - if (checked) { - widget.setHeaderTextAppearance(R.style.TextAppearance_AppCompat_Large); - widget.setDateTextAppearance(R.style.TextAppearance_AppCompat_Medium); - widget.setWeekDayTextAppearance(R.style.TextAppearance_AppCompat_Medium); - } else { - widget.setHeaderTextAppearance(R.style.TextAppearance_MaterialCalendarWidget_Header); - widget.setDateTextAppearance(R.style.TextAppearance_MaterialCalendarWidget_Date); - widget.setWeekDayTextAppearance(R.style.TextAppearance_MaterialCalendarWidget_WeekDay); - } - widget.setShowOtherDates(checked ? MaterialCalendarView.SHOW_ALL : MaterialCalendarView.SHOW_NONE); - } - - @OnCheckedChanged(R.id.check_page_enabled) - void onPageEnabledChecked(boolean checked) { - widget.setPagingEnabled(checked); - } - - @OnCheckedChanged(R.id.dynamic_height_enabled) - void onDynamicHeightChecked(boolean checked) { - widget.setDynamicHeightEnabled(checked); - } - - @OnClick(R.id.button_previous) - void onPreviousClicked() { - widget.goToPrevious(); - } - - @OnClick(R.id.button_next) - void onNextClicked() { - widget.goToNext(); - } - - @OnClick(R.id.button_min_date) - void onMinClicked() { - showDatePickerDialog(this, widget.getMinimumDate(), - (view, year, monthOfYear, dayOfMonth) -> - widget.state().edit() - .setMinimumDate(CalendarDay.from(year, monthOfYear + 1, dayOfMonth)) - .commit() - ); - } - - @OnClick(R.id.button_max_date) - void onMaxClicked() { - showDatePickerDialog(this, widget.getMaximumDate(), - (view, year, monthOfYear, dayOfMonth) -> - widget.state().edit() - .setMaximumDate(CalendarDay.from(year, monthOfYear + 1, dayOfMonth)) - .commit() - ); - } - - @OnClick(R.id.button_selected_date) - void onSelectedClicked() { - showDatePickerDialog(this, widget.getSelectedDate(), - (view, year, monthOfYear, dayOfMonth) -> - widget.setSelectedDate(CalendarDay.from(year, monthOfYear + 1, dayOfMonth)) - ); - } - - @OnClick(R.id.button_toggle_topbar) - void onToggleTopBarClicked() { - widget.setTopbarVisible(!widget.getTopbarVisible()); - } - - Random random = new Random(); - - @OnClick(R.id.button_set_colors) - void onColorsClicked() { - int color = Color.HSVToColor(new float[]{ - random.nextFloat() * 360, - 1f, - 0.75f - }); - widget.setArrowColor(color); - widget.setSelectionColor(color); - } - - @OnClick(R.id.button_set_tile_size) - void onTileSizeClicked() { - final NumberPicker view = new NumberPicker(this); - view.setMinValue(24); - view.setMaxValue(64); - view.setWrapSelectorWheel(false); - view.setValue(currentTileSize); - new AlertDialog.Builder(this) - .setView(view) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(@NonNull DialogInterface dialog, int which) { - currentTileSize = view.getValue(); - widget.setTileSizeDp(currentTileSize); - } - }) - .show(); - } - - @OnClick(R.id.button_set_width_height) - void onTileWidthHeightClicked() { - final LinearLayout layout = new LinearLayout(this); - layout.setOrientation(LinearLayout.HORIZONTAL); - final NumberPicker pickerWidth = new NumberPicker(this); - pickerWidth.setMinValue(24); - pickerWidth.setMaxValue(64); - pickerWidth.setWrapSelectorWheel(false); - pickerWidth.setValue(currentTileWidth); - final NumberPicker pickerHeight = new NumberPicker(this); - pickerHeight.setMinValue(24); - pickerHeight.setMaxValue(64); - pickerHeight.setWrapSelectorWheel(false); - pickerHeight.setValue(currentTileHeight); - layout.addView(pickerWidth); - layout.addView(pickerHeight); - new AlertDialog.Builder(this) - .setView(layout) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(@NonNull DialogInterface dialog, int which) { - currentTileWidth = pickerWidth.getValue(); - currentTileHeight = pickerHeight.getValue(); - widget.setTileSize(-1); - widget.setTileWidthDp(currentTileWidth); - widget.setTileHeightDp(currentTileHeight); - } - }) - .show(); - } - - @OnClick(R.id.button_clear_selection) - void onClearSelection() { - widget.clearSelection(); - } - - @OnClick(R.id.button_selection_mode) - void onChangeSelectionMode() { - CharSequence[] items = { - "No Selection", - "Single Date", - "Multiple Dates", - "Range of Dates" - }; - new AlertDialog.Builder(this) - .setTitle("Selection Mode") - .setSingleChoiceItems(items, widget.getSelectionMode(), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - widget.setSelectionMode(which); - dialog.dismiss(); - } - }) - .show(); - } - - @OnClick(R.id.button_change_orientation) - void onButtonChangeOrientation() { - widget.setTitleAnimationOrientation( - widget.getTitleAnimationOrientation() == MaterialCalendarView.VERTICAL - ? MaterialCalendarView.HORIZONTAL - : MaterialCalendarView.VERTICAL); - - Toast.makeText(this, - widget.getTitleAnimationOrientation() == MaterialCalendarView.VERTICAL - ? "Vertical" - : "Horizontal", - Toast.LENGTH_SHORT).show(); - } - - private static final DayOfWeek[] DAYS_OF_WEEK = { - DayOfWeek.SUNDAY, - DayOfWeek.MONDAY, - DayOfWeek.TUESDAY, - DayOfWeek.WEDNESDAY, - DayOfWeek.THURSDAY, - DayOfWeek.FRIDAY, - DayOfWeek.SATURDAY, + widget.setShowOtherDates( + checked ? MaterialCalendarView.SHOW_ALL : MaterialCalendarView.SHOW_NONE); + } + + @OnCheckedChanged(R.id.check_page_enabled) + void onPageEnabledChecked(boolean checked) { + widget.setPagingEnabled(checked); + } + + @OnCheckedChanged(R.id.dynamic_height_enabled) + void onDynamicHeightChecked(boolean checked) { + widget.setDynamicHeightEnabled(checked); + } + + @OnClick(R.id.button_previous) + void onPreviousClicked() { + widget.goToPrevious(); + } + + @OnClick(R.id.button_next) + void onNextClicked() { + widget.goToNext(); + } + + @OnClick(R.id.button_min_date) + void onMinClicked() { + showDatePickerDialog(this, widget.getMinimumDate(), + (view, year, monthOfYear, dayOfMonth) -> + widget.state().edit() + .setMinimumDate(CalendarDay.from(year, monthOfYear + 1, dayOfMonth)) + .commit() + ); + } + + @OnClick(R.id.button_max_date) + void onMaxClicked() { + showDatePickerDialog(this, widget.getMaximumDate(), + (view, year, monthOfYear, dayOfMonth) -> + widget.state().edit() + .setMaximumDate(CalendarDay.from(year, monthOfYear + 1, dayOfMonth)) + .commit() + ); + } + + @OnClick(R.id.button_selected_date) + void onSelectedClicked() { + showDatePickerDialog(this, widget.getSelectedDate(), + (view, year, monthOfYear, dayOfMonth) -> + widget.setSelectedDate(CalendarDay.from(year, monthOfYear + 1, dayOfMonth)) + ); + } + + @OnClick(R.id.button_toggle_topbar) + void onToggleTopBarClicked() { + widget.setTopbarVisible(!widget.getTopbarVisible()); + } + + Random random = new Random(); + + @OnClick(R.id.button_set_colors) + void onColorsClicked() { + int color = Color.HSVToColor(new float[] { + random.nextFloat() * 360, + 1f, + 0.75f + }); + widget.setArrowColor(color); + widget.setSelectionColor(color); + } + + @OnClick(R.id.button_set_tile_size) + void onTileSizeClicked() { + final NumberPicker view = new NumberPicker(this); + view.setMinValue(24); + view.setMaxValue(64); + view.setWrapSelectorWheel(false); + view.setValue(currentTileSize); + new AlertDialog.Builder(this) + .setView(view) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(@NonNull DialogInterface dialog, int which) { + currentTileSize = view.getValue(); + widget.setTileSizeDp(currentTileSize); + } + }) + .show(); + } + + @OnClick(R.id.button_set_width_height) + void onTileWidthHeightClicked() { + final LinearLayout layout = new LinearLayout(this); + layout.setOrientation(LinearLayout.HORIZONTAL); + final NumberPicker pickerWidth = new NumberPicker(this); + pickerWidth.setMinValue(24); + pickerWidth.setMaxValue(64); + pickerWidth.setWrapSelectorWheel(false); + pickerWidth.setValue(currentTileWidth); + final NumberPicker pickerHeight = new NumberPicker(this); + pickerHeight.setMinValue(24); + pickerHeight.setMaxValue(64); + pickerHeight.setWrapSelectorWheel(false); + pickerHeight.setValue(currentTileHeight); + layout.addView(pickerWidth); + layout.addView(pickerHeight); + new AlertDialog.Builder(this) + .setView(layout) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(@NonNull DialogInterface dialog, int which) { + currentTileWidth = pickerWidth.getValue(); + currentTileHeight = pickerHeight.getValue(); + widget.setTileSize(-1); + widget.setTileWidthDp(currentTileWidth); + widget.setTileHeightDp(currentTileHeight); + } + }) + .show(); + } + + @OnClick(R.id.button_clear_selection) + void onClearSelection() { + widget.clearSelection(); + } + + @OnClick(R.id.button_selection_mode) + void onChangeSelectionMode() { + CharSequence[] items = { + "No Selection", + "Single Date", + "Multiple Dates", + "Range of Dates" }; - - @OnClick(R.id.button_set_first_day) - void onFirstDayOfWeekClicked() { - int index = random.nextInt(DAYS_OF_WEEK.length); - widget.state().edit().setFirstDayOfWeek(DAYS_OF_WEEK[index]).commit(); - } - - @OnClick(R.id.button_weeks) - public void onSetWeekMode() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && animateModeTransition.isChecked()) { - TransitionManager.beginDelayedTransition(parent); - } - widget.state().edit().setCalendarDisplayMode(CalendarMode.WEEKS).commit(); - } - - @OnClick(R.id.button_months) - public void onSetMonthMode() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && animateModeTransition.isChecked()) { - TransitionManager.beginDelayedTransition(parent); - } - widget.state().edit().setCalendarDisplayMode(CalendarMode.MONTHS).commit(); + new AlertDialog.Builder(this) + .setTitle("Selection Mode") + .setSingleChoiceItems( + items, + widget.getSelectionMode(), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + widget.setSelectionMode(which); + dialog.dismiss(); + } + } + ) + .show(); + } + + @OnClick(R.id.button_change_orientation) + void onButtonChangeOrientation() { + widget.setTitleAnimationOrientation( + widget.getTitleAnimationOrientation() == MaterialCalendarView.VERTICAL + ? MaterialCalendarView.HORIZONTAL + : MaterialCalendarView.VERTICAL); + + Toast.makeText( + this, + widget.getTitleAnimationOrientation() == MaterialCalendarView.VERTICAL + ? "Vertical" + : "Horizontal", + Toast.LENGTH_SHORT + ).show(); + } + + private static final DayOfWeek[] DAYS_OF_WEEK = { + DayOfWeek.SUNDAY, + DayOfWeek.MONDAY, + DayOfWeek.TUESDAY, + DayOfWeek.WEDNESDAY, + DayOfWeek.THURSDAY, + DayOfWeek.FRIDAY, + DayOfWeek.SATURDAY, + }; + + @OnClick(R.id.button_set_first_day) + void onFirstDayOfWeekClicked() { + int index = random.nextInt(DAYS_OF_WEEK.length); + widget.state().edit().setFirstDayOfWeek(DAYS_OF_WEEK[index]).commit(); + } + + @OnClick(R.id.button_weeks) + public void onSetWeekMode() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && animateModeTransition.isChecked()) { + TransitionManager.beginDelayedTransition(parent); } + widget.state().edit().setCalendarDisplayMode(CalendarMode.WEEKS).commit(); + } - - public static void showDatePickerDialog(Context context, CalendarDay day, - DatePickerDialog.OnDateSetListener callback) { - if (day == null) { - day = CalendarDay.today(); - } - DatePickerDialog dialog = new DatePickerDialog( - context, 0, callback, day.getYear(), day.getMonth() - 1, day.getDay() - ); - dialog.show(); + @OnClick(R.id.button_months) + public void onSetMonthMode() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && animateModeTransition.isChecked()) { + TransitionManager.beginDelayedTransition(parent); } - - @Override - public void onDateLongClick(@NonNull MaterialCalendarView widget, @NonNull CalendarDay date) { - Toast.makeText(this, FORMATTER.format(date.getDate()), Toast.LENGTH_SHORT).show(); + widget.state().edit().setCalendarDisplayMode(CalendarMode.MONTHS).commit(); + } + + public static void showDatePickerDialog( + Context context, CalendarDay day, + DatePickerDialog.OnDateSetListener callback) { + if (day == null) { + day = CalendarDay.today(); } + DatePickerDialog dialog = new DatePickerDialog( + context, 0, callback, day.getYear(), day.getMonth() - 1, day.getDay() + ); + dialog.show(); + } + + @Override + public void onDateLongClick(@NonNull MaterialCalendarView widget, @NonNull CalendarDay date) { + Toast.makeText(this, FORMATTER.format(date.getDate()), Toast.LENGTH_SHORT).show(); + } } diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/MainActivity.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/MainActivity.java index a4f1e5fc..4e8ecbd8 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/MainActivity.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/MainActivity.java @@ -15,7 +15,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.TextView; - import java.util.List; /** @@ -23,75 +22,75 @@ */ public class MainActivity extends AppCompatActivity { - private static final String CATEGORY_SAMPLE = "com.prolificinteractive.materialcalendarview.sample.SAMPLE"; + private static final String CATEGORY_SAMPLE = + "com.prolificinteractive.materialcalendarview.sample.SAMPLE"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + RecyclerView list = findViewById(R.id.list); + list.setLayoutManager(new LinearLayoutManager(this)); + list.setAdapter(new ResolveInfoAdapter(this, getAllSampleActivities())); + } + + private List getAllSampleActivities() { + Intent filter = new Intent(); + filter.setAction(Intent.ACTION_RUN); + filter.addCategory(CATEGORY_SAMPLE); + return getPackageManager().queryIntentActivities(filter, 0); + } + + private void onRouteClicked(ResolveInfo route) { + ActivityInfo activity = route.activityInfo; + ComponentName name = new ComponentName(activity.applicationInfo.packageName, activity.name); + startActivity(new Intent(Intent.ACTION_VIEW).setComponent(name)); + } + + class ResolveInfoAdapter extends RecyclerView.Adapter { + + private final PackageManager pm; + private final LayoutInflater inflater; + private final List samples; + + private ResolveInfoAdapter(Context context, List resolveInfos) { + this.samples = resolveInfos; + this.inflater = LayoutInflater.from(context); + this.pm = context.getPackageManager(); + } @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - RecyclerView list = findViewById(R.id.list); - list.setLayoutManager(new LinearLayoutManager(this)); - list.setAdapter(new ResolveInfoAdapter(this, getAllSampleActivities())); + public ResolveInfoViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + View view = inflater.inflate(R.layout.item_route, viewGroup, false); + return new ResolveInfoViewHolder(view); } - private List getAllSampleActivities() { - Intent filter = new Intent(); - filter.setAction(Intent.ACTION_RUN); - filter.addCategory(CATEGORY_SAMPLE); - return getPackageManager().queryIntentActivities(filter, 0); + @Override + public void onBindViewHolder(ResolveInfoViewHolder viewHolder, int i) { + ResolveInfo item = samples.get(i); + viewHolder.textView.setText(item.loadLabel(pm)); } - private void onRouteClicked(ResolveInfo route) { - ActivityInfo activity = route.activityInfo; - ComponentName name = new ComponentName(activity.applicationInfo.packageName, activity.name); - startActivity(new Intent(Intent.ACTION_VIEW).setComponent(name)); + @Override + public int getItemCount() { + return samples.size(); } - class ResolveInfoAdapter extends RecyclerView.Adapter { - - private final PackageManager pm; - private final LayoutInflater inflater; - private final List samples; - - private ResolveInfoAdapter(Context context, List resolveInfos) { - this.samples = resolveInfos; - this.inflater = LayoutInflater.from(context); - this.pm = context.getPackageManager(); - } - - @Override - public ResolveInfoViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { - View view = inflater.inflate(R.layout.item_route, viewGroup, false); - return new ResolveInfoViewHolder(view); - } - - @Override - public void onBindViewHolder(ResolveInfoViewHolder viewHolder, int i) { - ResolveInfo item = samples.get(i); - viewHolder.textView.setText(item.loadLabel(pm)); - } - - @Override - public int getItemCount() { - return samples.size(); - } - - class ResolveInfoViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { - - public final TextView textView; - - public ResolveInfoViewHolder(View view) { - super(view); - this.textView = view.findViewById(android.R.id.text1); - view.setOnClickListener(this); - } - - @Override - public void onClick(@NonNull View v) { - onRouteClicked(samples.get(getAdapterPosition())); - } - } - } + class ResolveInfoViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + + public final TextView textView; + public ResolveInfoViewHolder(View view) { + super(view); + this.textView = view.findViewById(android.R.id.text1); + view.setOnClickListener(this); + } + + @Override + public void onClick(@NonNull View v) { + onRouteClicked(samples.get(getAdapterPosition())); + } + } + } } diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/MultipleSizeActivity.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/MultipleSizeActivity.java index f679c6d3..10cc9360 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/MultipleSizeActivity.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/MultipleSizeActivity.java @@ -8,9 +8,9 @@ * Displays various ways of sizing CalendarView */ public class MultipleSizeActivity extends AppCompatActivity { - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_multiple_size); - } + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_multiple_size); + } } diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/MultipleViewActivity.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/MultipleViewActivity.java index a0ec1a13..a0066ffe 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/MultipleViewActivity.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/MultipleViewActivity.java @@ -8,11 +8,9 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; - -import com.prolificinteractive.materialcalendarview.MaterialCalendarView; - import butterknife.BindView; import butterknife.ButterKnife; +import com.prolificinteractive.materialcalendarview.MaterialCalendarView; import org.threeten.bp.LocalDate; /** @@ -21,60 +19,60 @@ * , test activity with multiple MaterialCalendarViews */ public class MultipleViewActivity extends AppCompatActivity { - //number of MaterialCalendarViews to display in list - static final int NUM_ENTRIES = 3; + //number of MaterialCalendarViews to display in list + static final int NUM_ENTRIES = 3; - @BindView(R.id.calendar_list) - RecyclerView calendarList; + @BindView(R.id.calendar_list) + RecyclerView calendarList; - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_multiple); - ButterKnife.bind(this); + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_multiple); + ButterKnife.bind(this); - //setup RecyclerView - calendarList.setLayoutManager(new LinearLayoutManager(this)); - calendarList.setAdapter(new MultipleViewAdapter(this)); - } + //setup RecyclerView + calendarList.setLayoutManager(new LinearLayoutManager(this)); + calendarList.setAdapter(new MultipleViewAdapter(this)); + } - /** - * Adapter for RecyclerView - */ - class MultipleViewAdapter extends RecyclerView.Adapter { - final LayoutInflater inflater; + /** + * Adapter for RecyclerView + */ + class MultipleViewAdapter extends RecyclerView.Adapter { + final LayoutInflater inflater; - MultipleViewAdapter(final Context context) { - inflater = LayoutInflater.from(context); - } + MultipleViewAdapter(final Context context) { + inflater = LayoutInflater.from(context); + } - @Override - public EntryViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - final View view = inflater.inflate(R.layout.calendar_list_entry, parent, false); - return new EntryViewHolder(view); - } + @Override + public EntryViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + final View view = inflater.inflate(R.layout.calendar_list_entry, parent, false); + return new EntryViewHolder(view); + } - @Override - public int getItemCount() { - return NUM_ENTRIES; - } + @Override + public int getItemCount() { + return NUM_ENTRIES; + } - @Override - public void onBindViewHolder(EntryViewHolder holder, int position) { - //set selected date to today - holder.calendarView.setSelectedDate(LocalDate.now()); - } + @Override + public void onBindViewHolder(EntryViewHolder holder, int position) { + //set selected date to today + holder.calendarView.setSelectedDate(LocalDate.now()); + } - /** - * View holder for list entry - */ - class EntryViewHolder extends RecyclerView.ViewHolder { - final MaterialCalendarView calendarView; + /** + * View holder for list entry + */ + class EntryViewHolder extends RecyclerView.ViewHolder { + final MaterialCalendarView calendarView; - EntryViewHolder(final View itemView) { - super(itemView); - calendarView = itemView.findViewById(R.id.list_entry); - } - } + EntryViewHolder(final View itemView) { + super(itemView); + calendarView = itemView.findViewById(R.id.list_entry); + } } + } } diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/OldCalendarViewActivity.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/OldCalendarViewActivity.java index e15b2683..aabd146d 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/OldCalendarViewActivity.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/OldCalendarViewActivity.java @@ -4,39 +4,38 @@ import android.support.v7.app.AppCompatActivity; import android.widget.CalendarView; import android.widget.TextView; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; - import butterknife.BindView; import butterknife.ButterKnife; +import java.text.DateFormat; +import java.text.SimpleDateFormat; /** * Shows off the most basic usage */ public class OldCalendarViewActivity extends AppCompatActivity - implements CalendarView.OnDateChangeListener { + implements CalendarView.OnDateChangeListener { - private static final DateFormat FORMATTER = SimpleDateFormat.getDateInstance(); + private static final DateFormat FORMATTER = SimpleDateFormat.getDateInstance(); - @BindView(R.id.calendarView) - CalendarView widget; + @BindView(R.id.calendarView) + CalendarView widget; - @BindView(R.id.textView) - TextView textView; + @BindView(R.id.textView) + TextView textView; - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_old_calendarview); - ButterKnife.bind(this); + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_old_calendarview); + ButterKnife.bind(this); - widget.setOnDateChangeListener(this); - } + widget.setOnDateChangeListener(this); + } - @Override - public void onSelectedDayChange(CalendarView view, int year, int month, - int dayOfMonth) { - textView.setText(FORMATTER.format(view.getDate())); - } + @Override + public void onSelectedDayChange( + CalendarView view, int year, int month, + int dayOfMonth) { + textView.setText(FORMATTER.format(view.getDate())); + } } diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/SelectionModesActivity.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/SelectionModesActivity.java index 16d847e7..45135558 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/SelectionModesActivity.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/SelectionModesActivity.java @@ -4,18 +4,18 @@ import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; -import android.util.Log; import android.transition.TransitionManager; import android.view.ViewGroup; import android.widget.Toast; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnCheckedChanged; -import com.prolificinteractive.materialcalendarview.*; - +import com.prolificinteractive.materialcalendarview.CalendarDay; +import com.prolificinteractive.materialcalendarview.CalendarMode; +import com.prolificinteractive.materialcalendarview.MaterialCalendarView; +import com.prolificinteractive.materialcalendarview.OnDateSelectedListener; +import com.prolificinteractive.materialcalendarview.OnRangeSelectedListener; import com.prolificinteractive.materialcalendarview.sample.decorators.RangeDayDecorator; -import java.text.DateFormat; -import java.text.SimpleDateFormat; import java.util.List; import org.threeten.bp.format.DateTimeFormatter; diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/SwappableBasicActivityDecorated.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/SwappableBasicActivityDecorated.java index 02466178..aaa5ba6f 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/SwappableBasicActivityDecorated.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/SwappableBasicActivityDecorated.java @@ -3,7 +3,9 @@ import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; - +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; import com.prolificinteractive.materialcalendarview.CalendarDay; import com.prolificinteractive.materialcalendarview.CalendarMode; import com.prolificinteractive.materialcalendarview.MaterialCalendarView; @@ -11,63 +13,63 @@ import com.prolificinteractive.materialcalendarview.sample.decorators.HighlightWeekendsDecorator; import com.prolificinteractive.materialcalendarview.sample.decorators.MySelectorDecorator; import com.prolificinteractive.materialcalendarview.sample.decorators.OneDayDecorator; -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; import org.threeten.bp.LocalDate; import org.threeten.bp.Month; /** * Shows off the most basic usage */ -public class SwappableBasicActivityDecorated extends AppCompatActivity implements OnDateSelectedListener { - - private final OneDayDecorator oneDayDecorator = new OneDayDecorator(); +public class SwappableBasicActivityDecorated extends AppCompatActivity + implements OnDateSelectedListener { - @BindView(R.id.calendarView) MaterialCalendarView widget; + private final OneDayDecorator oneDayDecorator = new OneDayDecorator(); - @Override protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_basic_modes); - ButterKnife.bind(this); + @BindView(R.id.calendarView) MaterialCalendarView widget; - widget.setOnDateChangedListener(this); - widget.setShowOtherDates(MaterialCalendarView.SHOW_ALL); + @Override protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_basic_modes); + ButterKnife.bind(this); + widget.setOnDateChangedListener(this); + widget.setShowOtherDates(MaterialCalendarView.SHOW_ALL); - final LocalDate instance = LocalDate.now(); - widget.setSelectedDate(instance); + final LocalDate instance = LocalDate.now(); + widget.setSelectedDate(instance); - final LocalDate min = LocalDate.of(instance.getYear(), Month.JANUARY, 1); - final LocalDate max = LocalDate.of(instance.getYear(), Month.DECEMBER, 31); + final LocalDate min = LocalDate.of(instance.getYear(), Month.JANUARY, 1); + final LocalDate max = LocalDate.of(instance.getYear(), Month.DECEMBER, 31); - widget.state().edit().setMinimumDate(min).setMaximumDate(max).commit(); + widget.state().edit().setMinimumDate(min).setMaximumDate(max).commit(); - widget.addDecorators( - new MySelectorDecorator(this), - new HighlightWeekendsDecorator(), - oneDayDecorator - ); - } + widget.addDecorators( + new MySelectorDecorator(this), + new HighlightWeekendsDecorator(), + oneDayDecorator + ); + } - @Override - public void onDateSelected(@NonNull MaterialCalendarView widget, @NonNull CalendarDay date, boolean selected) { - //If you change a decorate, you need to invalidate decorators - oneDayDecorator.setDate(date.getDate()); - widget.invalidateDecorators(); - } + @Override + public void onDateSelected( + @NonNull MaterialCalendarView widget, + @NonNull CalendarDay date, + boolean selected) { + //If you change a decorate, you need to invalidate decorators + oneDayDecorator.setDate(date.getDate()); + widget.invalidateDecorators(); + } - @OnClick(R.id.button_weeks) - public void onSetWeekMode() { - widget.state().edit() - .setCalendarDisplayMode(CalendarMode.WEEKS) - .commit(); - } + @OnClick(R.id.button_weeks) + public void onSetWeekMode() { + widget.state().edit() + .setCalendarDisplayMode(CalendarMode.WEEKS) + .commit(); + } - @OnClick(R.id.button_months) - public void onSetMonthMode() { - widget.state().edit() - .setCalendarDisplayMode(CalendarMode.MONTHS) - .commit(); - } + @OnClick(R.id.button_months) + public void onSetMonthMode() { + widget.state().edit() + .setCalendarDisplayMode(CalendarMode.MONTHS) + .commit(); + } } diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/decorators/EventDecorator.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/decorators/EventDecorator.java index f13b2b1c..95079557 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/decorators/EventDecorator.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/decorators/EventDecorator.java @@ -4,7 +4,6 @@ import com.prolificinteractive.materialcalendarview.DayViewDecorator; import com.prolificinteractive.materialcalendarview.DayViewFacade; import com.prolificinteractive.materialcalendarview.spans.DotSpan; - import java.util.Collection; import java.util.HashSet; @@ -13,21 +12,21 @@ */ public class EventDecorator implements DayViewDecorator { - private int color; - private HashSet dates; + private int color; + private HashSet dates; - public EventDecorator(int color, Collection dates) { - this.color = color; - this.dates = new HashSet<>(dates); - } + public EventDecorator(int color, Collection dates) { + this.color = color; + this.dates = new HashSet<>(dates); + } - @Override - public boolean shouldDecorate(CalendarDay day) { - return dates.contains(day); - } + @Override + public boolean shouldDecorate(CalendarDay day) { + return dates.contains(day); + } - @Override - public void decorate(DayViewFacade view) { - view.addSpan(new DotSpan(5, color)); - } + @Override + public void decorate(DayViewFacade view) { + view.addSpan(new DotSpan(5, color)); + } } diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/decorators/HighlightWeekendsDecorator.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/decorators/HighlightWeekendsDecorator.java index f57d3815..22e5b500 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/decorators/HighlightWeekendsDecorator.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/decorators/HighlightWeekendsDecorator.java @@ -3,11 +3,9 @@ import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; - import com.prolificinteractive.materialcalendarview.CalendarDay; import com.prolificinteractive.materialcalendarview.DayViewDecorator; import com.prolificinteractive.materialcalendarview.DayViewFacade; - import org.threeten.bp.DayOfWeek; /** @@ -15,19 +13,19 @@ */ public class HighlightWeekendsDecorator implements DayViewDecorator { - private final Drawable highlightDrawable; - private static final int color = Color.parseColor("#228BC34A"); + private final Drawable highlightDrawable; + private static final int color = Color.parseColor("#228BC34A"); - public HighlightWeekendsDecorator() { - highlightDrawable = new ColorDrawable(color); - } + public HighlightWeekendsDecorator() { + highlightDrawable = new ColorDrawable(color); + } - @Override public boolean shouldDecorate(final CalendarDay day) { - final DayOfWeek weekDay = day.getDate().getDayOfWeek(); - return weekDay == DayOfWeek.SATURDAY || weekDay == DayOfWeek.SUNDAY; - } + @Override public boolean shouldDecorate(final CalendarDay day) { + final DayOfWeek weekDay = day.getDate().getDayOfWeek(); + return weekDay == DayOfWeek.SATURDAY || weekDay == DayOfWeek.SUNDAY; + } - @Override public void decorate(final DayViewFacade view) { - view.setBackgroundDrawable(highlightDrawable); - } + @Override public void decorate(final DayViewFacade view) { + view.setBackgroundDrawable(highlightDrawable); + } } diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/decorators/MySelectorDecorator.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/decorators/MySelectorDecorator.java index b8f38f62..f35b3bcc 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/decorators/MySelectorDecorator.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/decorators/MySelectorDecorator.java @@ -2,7 +2,6 @@ import android.app.Activity; import android.graphics.drawable.Drawable; - import com.prolificinteractive.materialcalendarview.CalendarDay; import com.prolificinteractive.materialcalendarview.DayViewDecorator; import com.prolificinteractive.materialcalendarview.DayViewFacade; @@ -13,19 +12,19 @@ */ public class MySelectorDecorator implements DayViewDecorator { - private final Drawable drawable; + private final Drawable drawable; - public MySelectorDecorator(Activity context) { - drawable = context.getResources().getDrawable(R.drawable.my_selector); - } + public MySelectorDecorator(Activity context) { + drawable = context.getResources().getDrawable(R.drawable.my_selector); + } - @Override - public boolean shouldDecorate(CalendarDay day) { - return true; - } + @Override + public boolean shouldDecorate(CalendarDay day) { + return true; + } - @Override - public void decorate(DayViewFacade view) { - view.setSelectionDrawable(drawable); - } + @Override + public void decorate(DayViewFacade view) { + view.setSelectionDrawable(drawable); + } } diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/decorators/OneDayDecorator.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/decorators/OneDayDecorator.java index cd67db01..e6735f4b 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/decorators/OneDayDecorator.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/decorators/OneDayDecorator.java @@ -3,12 +3,10 @@ import android.graphics.Typeface; import android.text.style.RelativeSizeSpan; import android.text.style.StyleSpan; - import com.prolificinteractive.materialcalendarview.CalendarDay; import com.prolificinteractive.materialcalendarview.DayViewDecorator; import com.prolificinteractive.materialcalendarview.DayViewFacade; import com.prolificinteractive.materialcalendarview.MaterialCalendarView; - import org.threeten.bp.LocalDate; /** @@ -16,27 +14,27 @@ */ public class OneDayDecorator implements DayViewDecorator { - private CalendarDay date; - - public OneDayDecorator() { - date = CalendarDay.today(); - } - - @Override - public boolean shouldDecorate(CalendarDay day) { - return date != null && day.equals(date); - } - - @Override - public void decorate(DayViewFacade view) { - view.addSpan(new StyleSpan(Typeface.BOLD)); - view.addSpan(new RelativeSizeSpan(1.4f)); - } - - /** - * We're changing the internals, so make sure to call {@linkplain MaterialCalendarView#invalidateDecorators()} - */ - public void setDate(LocalDate date) { - this.date = CalendarDay.from(date); - } + private CalendarDay date; + + public OneDayDecorator() { + date = CalendarDay.today(); + } + + @Override + public boolean shouldDecorate(CalendarDay day) { + return date != null && day.equals(date); + } + + @Override + public void decorate(DayViewFacade view) { + view.addSpan(new StyleSpan(Typeface.BOLD)); + view.addSpan(new RelativeSizeSpan(1.4f)); + } + + /** + * We're changing the internals, so make sure to call {@linkplain MaterialCalendarView#invalidateDecorators()} + */ + public void setDate(LocalDate date) { + this.date = CalendarDay.from(date); + } } diff --git a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/decorators/RangeDayDecorator.java b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/decorators/RangeDayDecorator.java index 1322d2b5..dfe3dd7f 100644 --- a/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/decorators/RangeDayDecorator.java +++ b/sample/src/main/java/com/prolificinteractive/materialcalendarview/sample/decorators/RangeDayDecorator.java @@ -1,19 +1,13 @@ package com.prolificinteractive.materialcalendarview.sample.decorators; import android.content.Context; -import android.graphics.Typeface; import android.graphics.drawable.Drawable; -import android.text.style.RelativeSizeSpan; -import android.text.style.StyleSpan; import com.prolificinteractive.materialcalendarview.CalendarDay; import com.prolificinteractive.materialcalendarview.DayViewDecorator; import com.prolificinteractive.materialcalendarview.DayViewFacade; import com.prolificinteractive.materialcalendarview.MaterialCalendarView; import com.prolificinteractive.materialcalendarview.sample.R; -import java.util.ArrayList; -import java.util.Date; import java.util.HashSet; -import java.util.List; /** * Decorate 2 days. diff --git a/sample/src/main/res/drawable/my_selector.xml b/sample/src/main/res/drawable/my_selector.xml index c73c955a..8d839141 100644 --- a/sample/src/main/res/drawable/my_selector.xml +++ b/sample/src/main/res/drawable/my_selector.xml @@ -2,12 +2,10 @@ - + - + - + \ No newline at end of file diff --git a/sample/src/main/res/drawable/today_circle_background.xml b/sample/src/main/res/drawable/today_circle_background.xml index c85c69f3..953e4714 100644 --- a/sample/src/main/res/drawable/today_circle_background.xml +++ b/sample/src/main/res/drawable/today_circle_background.xml @@ -1,7 +1,8 @@ + android:shape="oval" + > - + \ No newline at end of file diff --git a/sample/src/main/res/layout/activity_basic.xml b/sample/src/main/res/layout/activity_basic.xml index bca14146..c71b8736 100644 --- a/sample/src/main/res/layout/activity_basic.xml +++ b/sample/src/main/res/layout/activity_basic.xml @@ -11,19 +11,19 @@ tools:context=".BasicActivity" > - + - + \ No newline at end of file diff --git a/sample/src/main/res/layout/activity_basic_modes.xml b/sample/src/main/res/layout/activity_basic_modes.xml index d04b783c..43b86338 100644 --- a/sample/src/main/res/layout/activity_basic_modes.xml +++ b/sample/src/main/res/layout/activity_basic_modes.xml @@ -11,34 +11,34 @@ tools:context=".SwappableBasicActivityDecorated" > - + + + +