diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 00000000..d325b6dd --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,38 @@ +name: Publish + +on: + release: + # We'll run this workflow when a new GitHub release is created + types: [released] + +jobs: + publish: + name: Release build and publish + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v2 + - name: Set up JDK 11 + uses: actions/setup-java@v2 + with: + distribution: adopt + java-version: 11 + + # Builds the release artifacts of the library + - name: Release build + run: ./gradlew assembleRelease -x :sample-app:assembleRelease -x :sample-app-java:assembleRelease + + # Generates other artifacts (javadocJar is optional) + - name: Source jar and dokka + run: ./gradlew androidSourcesJar javadocJar + + # Runs upload, and then closes & releases the repository + - name: Publish to MavenCentral + run: ./gradlew publishReleasePublicationToSonatypeRepository --max-workers 1 closeAndReleaseSonatypeStagingRepository + env: + OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }} + OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} + SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }} + SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }} + SIGNING_KEY: ${{ secrets.SIGNING_KEY }} + SONATYPE_STAGING_PROFILE_ID: ${{ secrets.SONATYPE_STAGING_PROFILE_ID }} diff --git a/README.md b/README.md index dbaec97f..f2823287 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,20 @@ # `PrimeDatePicker` :zap: [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-PrimeDatePicker-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/7743) [![Android Weekly](https://img.shields.io/badge/Android%20Weekly-%23367-red.svg)](http://androidweekly.net/issues/issue-367) -[![Bintray](https://img.shields.io/bintray/v/aminography/maven/PrimeDatePicker?label=Bintray)](https://bintray.com/aminography/maven/PrimeDatePicker/_latestVersion) +![mavenCentral](https://img.shields.io/maven-central/v/com.aminography/primedatepicker?color=blue) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/c1c44ee8a3a14b0e8c963c36c8e586d8)](https://app.codacy.com/manual/aminography/PrimeDatePicker?utm_source=github.com&utm_medium=referral&utm_content=aminography/PrimeDatePicker&utm_campaign=Badge_Grade_Dashboard) [![API](https://img.shields.io/badge/minSdkVersion-13-important.svg)](https://android-arsenal.com/api?level=13) -First, **`PrimeDatePicker`** is a tool which provides picking a single day, multiple days, and a range of days. Second, you can use its `MonthView` and `CalendarView` as stand-alone views in your projects. +Firstly, **`PrimeDatePicker`** is a tool that provides picking a single day, multiple days, and a range of days. Secondly, you can use internal elements like `MonthView` and `CalendarView` as stand-alone views in your projects. ![](static/prime_logo.png) - - - - + + + + @@ -28,6 +28,23 @@ First, **`PrimeDatePicker`** is a tool which provides picking a single day, mult
+Table of Contents +----------------- + +- [Core Logic](#core-logic) +- [Main Characteristics](#main-characteristics) +- [Download](#download) +- [Usage](#usage) + - [Java Example](#java-example) + - [Builder Configurations](#builder-configurations) + - [Input Calendar Configurations](#input-calendar-configurations) +- [Customizing Theme](#customizing-theme) + - [Customizing Texts](#customizing-texts) +- [Stand-Alone Views](#stand-alone-views) +- [Change Log](#change-log) + +
+ Core Logic ---------- The ❤️ of this library is provided by [**PrimeCalendar**](https://github.com/aminography/PrimeCalendar). @@ -37,709 +54,362 @@ The ❤️ of this library is provided by [**PrimeCalendar**](https://github.com Main Characteristics -------------------- - Endless Scrolling -- Fully Customizable Views & Theme -- Regarding Material Design +- Fully Customizable Views & Themes +- Align With Material Design - Fluent UI - RTL Support - Landscape Support - Various Calendar Types - Various Date Picking Strategies -- Showing Both Dialog & BottomSheet +- Dialog & BottomSheet Presentations - Fast Goto -#### :dart: Download [SampleApp.apk](https://github.com/aminography/PrimeDatePicker/releases/download/v3.1.1/sample-app-release.apk) +#### :dart: Download [SampleApp.apk](https://github.com/aminography/PrimeDatePicker/releases/download/v3.4.0/sample-app-release.apk)
Download -------- -**`PrimeDatePicker`** is available on [bintray](https://bintray.com/aminography/maven/PrimeDatePicker) to download using build tools systems. Add the following lines to your `build.gradle` file: +**`PrimeDatePicker`** is available on `MavenCentral` to download using build tools systems. Add the following lines to your `build.gradle` file: ```gradle -repositories { - jcenter() -} - dependencies { - implementation 'com.aminography:primedatepicker:3.2.0' - implementation 'com.aminography:primecalendar:1.3.0' + implementation 'com.aminography:primedatepicker:3.6.0' + implementation 'com.aminography:primecalendar:1.7.0' } ```
Usage ------------------ -To enjoy `PrimeDatePicker`, create an instance of it using builder pattern, like the following snippets: - -> Kotlin -```kotlin +----- -val multipleDaysPickCallback = MultipleDaysPickCallback { multipleDays -> - // TODO -} +To enjoy `PrimeDatePicker`, create an instance using a builder pattern in simple 4 steps. -val themeFactory = DarkThemeFactory() - -val today = CivilCalendar() // Causes a Civil date picker, also today as the starting date - -val datePicker = PrimeDatePicker.bottomSheetWith(today) // or dialogWith(today) - .pickMultipleDays(multipleDaysPickCallback) // Passing callback is optional, can be set later using setDayPickCallback() - .minPossibleDate(minDateCalendar) // Optional - .maxPossibleDate(maxDateCalendar) // Optional - .disabledDays(disabledDaysList) // Optional - .firstDayOfWeek(Calendar.MONDAY) // Optional - .applyTheme(themeFactory) // Optional - .build() +1. Decide on **BottomSheet** or **Dialog** representation along with an initial calendar: +```kotlin +// To show a date picker with Civil dates, also today as the starting date +val today = CivilCalendar() -datePicker.show(supportFragmentManager, "SOME_TAG") +val datePicker = PrimeDatePicker.bottomSheetWith(today) // or dialogWith(today) ``` -
- -> Java -```java -SingleDayPickCallback singleDayPickCallback = new SingleDayPickCallback() { - @Override - public void onSingleDayPicked(PrimeCalendar singleDay) { - // TODO - } -}; - -BaseThemeFactory themeFactory = new LightThemeFactory(); - -PrimeCalendar today = new JapaneseCalendar(); // Causes a Japanese date picker, also today as the starting date +2. Decide on picking strategy along with passing a proper callback: +```kotlin +val callback = SingleDayPickCallback { day -> + // TODO +} -PrimeDatePicker datePicker = PrimeDatePicker.Companion.dialogWith(today) // or bottomSheetWith(today) - .pickSingleDay(singleDayPickCallback) // Passing callback is optional, can be set later using setDayPickCallback() - .minPossibleDate(minDateCalendar) // Optional - .maxPossibleDate(maxDateCalendar) // Optional - .disabledDays(disabledDaysList) // Optional - .firstDayOfWeek(Calendar.MONDAY) // Optional - .applyTheme(themeFactory) // Optional - .build(); +val today = CivilCalendar() -datePicker.show(getSupportFragmentManager(), "SOME_TAG"); +val datePicker = PrimeDatePicker.bottomSheetWith(today) + .pickSingleDay(callback) // or pickRangeDays(callback) or pickMultipleDays(callback) ``` -
- -### Configurations Based on Input Calendar - -`PrimeDatePicker` reads some configurations from the input calendar, so they are reflected to the date picker. For example: +3. Apply some optional configurations: ```kotlin -// shows a Persian calendar, but in English language which leads to LTR direction -val calendar = PersianCalendar(Locale.ENGLISH).also { - it.year = 1398 // customizes starting year - it.month = 7 // customizes starting month - it.firstDayOfWeek = Calendar.MONDAY // sets first day of week to Monday -} +... -val datePicker = PrimeDatePicker.bottomSheetWith(calendar) - .pickSingleDay(singleDayPickCallback) - ... - .build() +val datePicker = PrimeDatePicker.bottomSheetWith(today) + .pickSingleDay(callback) + .initiallyPickedSingleDay(pickedDay) + ... ``` -
- -### Customizing Theme - -`PrimeDatePicker` is fully customizable and you can fit its view to what you desire. -Almost everything is customizable, such as: text size & color, background & element color, padding, font typeface, string formatter, calendar animation & transition parameters, *etc*. - -In this way, a theme factory class is provided which declares theme parameters. -A concrete subclass of this class realizes the parameters to be used by views. -By default, there are two concrete subclasses: -[`DarkThemeFactory`](library/src/main/java/com/aminography/primedatepicker/picker/theme/DarkThemeFactory.kt) -and -[`LightThemeFactory`](library/src/main/java/com/aminography/primedatepicker/picker/theme/LightThemeFactory.kt) -that you can override their parameters or inherit a class from or make your own theme factory. - -Here is an example of how to override theme parameters in `Kotlin` as well as `Java`: - -> Kotlin +4. Build the date picker and show it: ```kotlin -val themeFactory = object : LightThemeFactory() { - - override val typefacePath: String? - get() = "fonts/Roboto-Regular.ttf" - - override val calendarViewPickedDayInRangeBackgroundColor: Int - get() = getColor(R.color.red100) - - override val calendarViewPickedDayInRangeLabelTextColor: Int - get() = getColor(R.color.gray900) +val callback = SingleDayPickCallback { day -> + // TODO +} - override val calendarViewWeekLabelFormatter: LabelFormatter - get() = { primeCalendar -> - when (primeCalendar[Calendar.DAY_OF_WEEK]) { - Calendar.SATURDAY, - Calendar.SUNDAY -> String.format("%s😍", primeCalendar.weekDayNameShort) - else -> String.format("%s😁", primeCalendar.weekDayNameShort) - } - } +val today = CivilCalendar() - override val calendarViewWeekLabelTextColors: SparseIntArray - get() = SparseIntArray(7).apply { - val red = getColor(R.color.red300) - val green = getColor(R.color.green400) - put(Calendar.SATURDAY, red) - put(Calendar.SUNDAY, red) - put(Calendar.MONDAY, green) - put(Calendar.TUESDAY, green) - put(Calendar.WEDNESDAY, green) - put(Calendar.THURSDAY, green) - put(Calendar.FRIDAY, green) - } +val datePicker = PrimeDatePicker.bottomSheetWith(today) + .pickSingleDay(callback) + .initiallyPickedSingleDay(pickedDay) + .build() - // Other customizations... -} +datePicker.show(supportFragmentManager, "SOME_TAG") ``` -
Picking Multiple Days
Example for Civil
Picking a Range of Days
Example for Persian
Picking a Single Day
Example for Hijri
Goto View
Example for Japanese
Multiple Days | Civil
BottomSheet | Dark
Range of Days | Persian
BottomSheet | Light
Single Day | Hijri
Dialog | Light
Goto Feature | Japanese
Dialog | Dark
- - - - - - - - +
-
Result:
+### Java Example > Java ```java -BaseThemeFactory themeFactory = new LightThemeFactory() { - - @NotNull +SingleDayPickCallback callback = new SingleDayPickCallback() { @Override - public PrimeCalendarView.FlingOrientation getCalendarViewFlingOrientation() { - return PrimeCalendarView.FlingOrientation.HORIZONTAL; - } - - @Override - public int getSelectionBarBackgroundColor() { - return super.getColor(R.color.green300); + public void onSingleDayPicked(PrimeCalendar singleDay) { + // TODO } - - // Other customizations... }; -``` - -
-### Customizing Texts +// To show a date picker with Japanese dates, also today as the starting date +PrimeCalendar today = new JapaneseCalendar(); -If you want to change some texts in `PrimeDatePicker`, such as a button text, the current solution is to -define some strings in your project's `strings.xml` with equal name defined in the library's `strings.xml`, to override them. - -
-
- -Stand-Alone Views ------------------ -In addition to use **`PrimeDatePicker`** as a date picker tool, it is possible to employ stand-alone views in your project. -They are **`PrimeMonthView`** & **`PrimeCalendarView`** which can be used in layout `xml` files or instantiated programmatically. -For example: - -> xml -```xml - -``` +PrimeDatePicker datePicker = PrimeDatePicker.Companion.dialogWith(today) + .pickSingleDay(callback) + .build(); -> Programmatically -```kotlin -val monthView = PrimeMonthView(context) +datePicker.show(getSupportFragmentManager(), "SOME_TAG"); ```
-### 1. XML Attributes -Applying customization has been provided for `PrimeMonthView` and `PrimeCalendarView` by using `xml` attributes as well as setting them programmatically. -For example: - -> xml -```xml - -``` +### Builder Configurations -> Programmatically -```kotlin -calendarView.pickedDayBackgroundColor = Color.BLUE -``` +There are several builder functions applying relevant configurations on the date picker.
-### 1.1. Common attributes for `PrimeMonthView` & `PrimeCalendarView`: - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - +
AttributeType
• calendarTypeenum
Specifies the calendar type which is shown by this view. Its possible values are: civil, persian, hijri, and japanese.FunctionPicking Strategy
• monthLabelTextColorcolor
Specifies the text color of month name label.
• weekLabelTextColorcolor
Specifies the text color of week day name labels.
• dayLabelTextColorcolor
Specifies the text color of day number labels.
• todayLabelTextColorcolor
Specifies the text color of day number label which belongs to today.
• pickedDayLabelTextColorcolor
Specifies the text color of day number labels when they are picked.
• pickedDayBackgroundColorcolor
Specifies the background color of day numbers when they are picked.
• disabledDayLabelTextColorcolor
Specifies the text color of day number labels when they are disabled.
• monthLabelTextSizedimension
Specifies the text size of month name label.
• weekLabelTextSizedimension
Specifies the text size of week day name labels.
• dayLabelTextSizedimension• minPossibleDate(minDate: PrimeCalendar)ALL
Specifies the text size of day number labels.Specifies the minimum feasible date to be shown in date picker, which is selectable.
• monthLabelTopPaddingdimension• maxPossibleDate(maxDate: PrimeCalendar)ALL
Specifies the top padding of month name label.Specifies the maximum feasible date to be shown in date picker, which is selectable.
• monthLabelBottomPaddingdimension• firstDayOfWeek(firstDayOfWeek: Int)ALL
Specifies the bottom padding of month name label.Specifies the day that should be considered as the start of the week. Possible values are: Calendar.SUNDAY, Calendar.MONDAY, etc.
• weekLabelTopPaddingdimension• disabledDays(disabledDays: List<PrimeCalendar>)ALL
Specifies the top padding of week day name labels.Specifies the list of disabled days, which aren't selectable.
• weekLabelBottomPaddingdimension• applyTheme(themeFactory: ThemeFactory)ALL
Specifies the bottom padding of week day name labels.Specifies the theme.
• dayLabelVerticalPaddingdimension• initiallyPickedSingleDay(pickedDay: PrimeCalendar)SingleDay
Specifies the vertical padding (top and bottom) of day number labels.Specifies initially picked day when the date picker has just shown.
• showTwoWeeksInLandscapeboolean• initiallyPickedRangeDays(startDay: PrimeCalendar, endDay: PrimeCalendar)RangeDays
When it sets true, month view shows two weeks (14 days) in each row for landscape screen orientation.Specifies initially picked range of days when the date picker has just shown.
• animateSelectionboolean• autoSelectPickEndDay(autoSelect: Boolean)RangeDays
When it sets true, selected day/days will appear with animation.Specifies automatic selection of picking end day when the start day gets picked.
• animationDurationinteger• initiallyPickedMultipleDays(pickedDays: List<PrimeCalendar>)MultipleDays
Specifies the duration of day selection animation.Specifies initially picked multiple days when the date picker has just shown.

-### 1.2. `PrimeCalendarView` Specific Attributes: +### Input Calendar Configurations - +In addition to the builder functions, `PrimeDatePicker` receives some configurations from the input calendar. For example: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AttributeType
• flingOrientationenum
Specifies the fling orientation of calendar view. Its possible values are: vertical, horizontal.
• dividerColorcolor
Specifies the color of divider lines separating month views.
• dividerThicknessdimension
Specifies the thickness of divider lines separating month views.
• dividerInsetLeftdimension
Specifies the left margin of divider lines when the fling orientation is vertical.
• dividerInsetRightdimension
Specifies the right margin of divider lines when the fling orientation is vertical.
• dividerInsetTopdimension
Specifies the top margin of divider lines when the fling orientation is horizontal.
• dividerInsetBottomdimension
Specifies the bottom margin of divider lines when the fling orientation is horizontal.
• loadFactorinteger
Specifies the number of month to be load in pagination (endless scrolling).
• maxTransitionLengthinteger
Specifies the maximum number of month that are shown between current and target in transitions. It's used when goto method has called.
• transitionSpeedFactorfloat
Specifies the speed factor of scrolling in transitions. It's used when goto method has called.
+```kotlin +// shows a Persian calendar, but in English language, which leads to LTR direction +val calendar = PersianCalendar(Locale.ENGLISH).also { + it.year = 1398 // determines starting year + it.month = 7 // determines starting month + it.firstDayOfWeek = Calendar.MONDAY // sets first day of week to Monday +} + +val datePicker = PrimeDatePicker.bottomSheetWith(calendar) + ... + .build() +```
-### 2. Other Variables (Common for `PrimeMonthView` & `PrimeCalendarView`) -These variables are only accessible programmatically to get or set. (Available by getter and setter methods in java) +Customizing Theme +----------------- - +`PrimeDatePicker` is fully customizable and you can tailor it to what you desire. +Almost everything you see is customizable. For example: +- text sizes & colors +- background & element colors +- padding & distances +- font typeface +- string formatter +- calendar animations & transition parameters +- *etc* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +In this way, a set of customizable theme factory classes are provided to specify theme parameters. +By default, there are two concrete subclasses for the them factory: - - - - - - - +- [`DarkThemeFactory`](library/src/main/java/com/aminography/primedatepicker/picker/theme/DarkThemeFactory.kt) +- [`LightThemeFactory`](library/src/main/java/com/aminography/primedatepicker/picker/theme/LightThemeFactory.kt) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +You can override their parameters, or inherit a class from, or make your own theme factory. -
VariableType
• typefaceTypeface
Specifies the typeface of showing texts.
• pickedSingleDayCalendarPrimeCalendar
Specifies the single picked date.
• pickedRangeStartCalendarPrimeCalendar
Specifies the start date of the picked range.
• pickedRangeEndCalendarPrimeCalendar
Specifies the end date of the picked range.
• pickedMultipleDaysListList<PrimeCalendar>
Specifies the list of multiple picked dates.
• minDateCalendarPrimeCalendar
Specifies the minimum feasible date of the view.
• maxDateCalendarPrimeCalendar
Specifies the maximum feasible date of the view.
• pickTypePickType
Specifies the date picking type of the view. Its possible values are: SINGLE, RANGE_START, RANGE_END, MULTIPLE, NOTHING.
• animationInterpolatorInterpolator
Specifies the interpolator of day selection animation.
+Here is an example of how to override theme parameters to customize it: -
+```kotlin +val themeFactory = object : LightThemeFactory() { -### 3. Listener (Common for `PrimeMonthView` & `PrimeCalendarView`) -You can listen to day picking actions by setting an instance of [OnDayPickedListener](library/src/main/java/com/aminography/primedatepicker/common/OnDayPickedListener.java) to the views. -For example: + override val typefacePath: String? + get() = "fonts/Righteous-Regular.ttf" + + override val dialogBackgroundColor: Int + get() = getColor(R.color.yellow100) -```kotlin -monthView.onDayPickedListener = object : OnDayPickedListener { + override val calendarViewBackgroundColor: Int + get() = getColor(R.color.yellow100) - override fun onDayPicked(pickType: PickType, - singleDay: PrimeCalendar?, - startDay: PrimeCalendar?, - endDay: PrimeCalendar?, - multipleDays: List?) { - // TODO - } -} -``` + override val pickedDayBackgroundShapeType: BackgroundShapeType + get() = BackgroundShapeType.ROUND_SQUARE -
+ override val calendarViewPickedDayBackgroundColor: Int + get() = getColor(R.color.green800) + + override val calendarViewPickedDayInRangeBackgroundColor: Int + get() = getColor(R.color.green400) -Locale -------------------------------------------- -`PrimeMonthView` and `PrimeCalendarView` (consequently `PrimeDatePicker`) have been implemented with localization capabilities. -By choosing locale for the `PrimeCalendar` instance which is passed to `goto` method, or by setting it directly to the views, you can localize names, digits, and layout direction. + override val calendarViewPickedDayInRangeLabelTextColor: Int + get() = getColor(R.color.gray900) -#### Localization example for `PrimeMonthView` using `PersianCalendar`: + override val calendarViewTodayLabelTextColor: Int + get() = getColor(R.color.purple200) -
+ override val calendarViewWeekLabelFormatter: LabelFormatter + get() = { primeCalendar -> + when (primeCalendar[Calendar.DAY_OF_WEEK]) { + Calendar.SATURDAY, + Calendar.SUNDAY -> String.format("%s😍", primeCalendar.weekDayNameShort) + else -> String.format("%s", primeCalendar.weekDayNameShort) + } + } - + override val calendarViewWeekLabelTextColors: SparseIntArray + get() = SparseIntArray(7).apply { + val red = getColor(R.color.red300) + val indigo = getColor(R.color.indigo500) + put(Calendar.SATURDAY, red) + put(Calendar.SUNDAY, red) + put(Calendar.MONDAY, indigo) + put(Calendar.TUESDAY, indigo) + put(Calendar.WEDNESDAY, indigo) + put(Calendar.THURSDAY, indigo) + put(Calendar.FRIDAY, indigo) + } - - - - + override val calendarViewShowAdjacentMonthDays: Boolean + get() = true - - - - + override val selectionBarBackgroundColor: Int + get() = getColor(R.color.brown600) -
monthView.goto(PersianCalendar())
// or
monthView.locale = Locale("fa")
monthView.goto(PersianCalendar(Locale.ENGLISH))
// or
monthView.locale = Locale.ENGLISH
+ override val selectionBarRangeDaysItemBackgroundColor: Int + get() = getColor(R.color.orange700) +} +```
-#### Localization example for `PrimeCalendarView` using `HijriCalendar`: +Using above theme, we can transform the light theme (left picture) to the right one.
- - + + - - + +
calendarView.goto(HijriCalendar())
// or
calendarView.locale = Locale("ar")
calendarView.goto(HijriCalendar(Locale.ENGLISH))
// or
calendarView.locale = Locale.ENGLISH
Normal Light ThemeCustomized Light Theme

-Change Log ----------- -### Version 3.2.0 -- Ability to show adjacent months' days in the current month (using `showAdjacentMonthDays`) and customize their text color. -- Ability to change the background shape of the selected days (using `pickedDayBackgroundShapeType` and `pickedDayRoundSquareCornerRadius`). -- Minor improvements. - -### Version 3.1.1 -- Some UI adjustments. - -### Version 3.1.0 -- Adding ability to change background and text color of days in selected range. -- Improvement in japanese text and temporal names. -- Minor bug fixed. - -### Version 3.0.4 -- A minor bug fixed. +> Java Theme Customization Example +```java +BaseThemeFactory themeFactory = new LightThemeFactory() { + + @NotNull + @Override + public PrimeCalendarView.FlingOrientation getCalendarViewFlingOrientation() { + return PrimeCalendarView.FlingOrientation.HORIZONTAL; + } + + @Override + public int getSelectionBarBackgroundColor() { + return super.getColor(R.color.green300); + } + + // Other customizations... +}; +``` -### Version 3.0.0 -- Builder mechanism has changed a bit. -- Adding full customization ability using a user configurable theme factory. -- Ability to show the date picker as a dialog using `PrimeDatePicker.dialogWith` method as well as `PrimeDatePicker.bottomSheetWith` to show a bottom sheet. -- Ability to specify a list of disabled days. +
-### Version 2.0.0 -- Builder mechanism has changed. -- Picking multiple days has better UX. -- Adding Goto by tapping on Month-Year. -- Picking animation has improved. -- Possibility to change start day of week. -- Adding RTL support in bottom sheet.``` +### Customizing Texts -### Version 1.1.0 -- Migrated to AndroidX +If you want to change some texts in `PrimeDatePicker`, such as a button text, the current solution is to +define some strings in your project's `strings.xml` with equal name defined in the library's `strings.xml`, to override them. -### Version 1.0.16 -- Ability to pick multiple days using `MULTIPLE` PickType. +
-### Version 1.0.15 -- A minor bug is fixed. +Stand-Alone Views +----------------- -### Version 1.0.14 -- Animation for selected days using `animateSelection`, `animationDuration`, and `animationInterpolator` attributes. +To see how to use **`PrimeMonthView`** & **`PrimeCalendarView`**, [refer to wiki page](https://github.com/aminography/PrimeDatePicker/wiki#stand-alone-views) .
-Third-Party Libraries ---------------------- -**• PrimeCalendar** () +Change Log +---------- -**• PrimeAdapter** () +The change log is available [here](https://github.com/aminography/PrimeDatePicker/wiki/Change-Log).
diff --git a/build.gradle b/build.gradle index 568024bd..de31d12f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,71 +1,27 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. +apply plugin: 'io.github.gradle-nexus.publish-plugin' +apply from: rootProject.file('scripts/publish-root.gradle') buildscript { - ext.kotlin_version = '1.3.72' + apply from: rootProject.file('scripts/versions.gradle') - ext.primecalendar_version = '1.3.0' + ext.primecalendar_version = '1.4.0' - ext.material_version = '1.1.0' - ext.appcompat_version = '1.1.0' - ext.constraintlayout_version = '1.1.3' ext.lifecycle_version = '2.2.0' - ext.junit_version = '4.13' - ext.androidx_junit_version = '1.1.1' - ext.androidx_espresso_version = '3.2.0' - repositories { google() - jcenter() mavenCentral() + maven { url "https://plugins.gradle.org/m2/" } } dependencies { - classpath 'com.android.tools.build:gradle:4.0.0' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - - classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4' - } -} - -allprojects { - repositories { - google() - jcenter() - mavenCentral() + classpath plugin.android.gradle + classpath plugin.jetbrains.kotlin + classpath plugin.jetbrains.dokka + classpath plugin.nexus.publish } } task clean(type: Delete) { delete rootProject.buildDir } - -ext { - bintrayRepo = 'maven' - bintrayName = 'PrimeDatePicker' - orgName = 'aminography' - - publishedGroupId = 'com.aminography' - artifact = 'primedatepicker' - - libraryVersionCode = 320 - libraryVersion = "3.2.0" - - libraryName = 'PrimeDatePicker' - libraryDescription = 'PrimeDatePicker is a date picker tool.' - - siteUrl = 'https://github.com/aminography/PrimeDatePicker' - gitUrl = 'https://github.com/aminography/PrimeDatePicker.git' - - developerId = 'aminography' - developerName = 'Mohammad Amin Hassani' - developerEmail = 'aminography@gmail.com' - - licenseName = 'The Apache Software License, Version 2.0' - licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt' - allLicenses = ["Apache-2.0"] -} diff --git a/gradle/bintray-android.gradle b/gradle/bintray-android.gradle deleted file mode 100644 index be31dd42..00000000 --- a/gradle/bintray-android.gradle +++ /dev/null @@ -1,72 +0,0 @@ -apply plugin: 'com.jfrog.bintray' - -version = libraryVersion - -task sourcesJar(type: Jar) { - from android.sourceSets.main.java.srcDirs - classifier = 'sources' -} - -task javadoc(type: Javadoc) { - source = android.sourceSets.main.java.srcDirs - classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) -} - -task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' - from javadoc.destinationDir -} - -// Avoid Kotlin docs error -tasks.withType(Javadoc) { - enabled = false -} - -artifacts { - archives javadocJar - archives sourcesJar -} - -def _user = System.getenv("BINTRAY_USER") -def _key = System.getenv("BINTRAY_API_KEY") -def _passphrase = System.getenv("BINTRAY_PASSPHRASE") - -if (project.rootProject.file('local.properties').exists()) { - Properties properties = new Properties() - properties.load(project.rootProject.file('local.properties').newDataInputStream()) - - def local_user = properties.getProperty("bintray.user") - if (local_user != null) _user = local_user - - def local_key = properties.getProperty("bintray.apikey") - if (local_key != null) _key = local_key - - def local_passphrase = properties.getProperty("bintray.gpg.password") - if (local_passphrase != null) _passphrase = local_passphrase -} - -bintray { - user = _user - key = _key - override = true - configurations = ['archives'] - pkg { - repo = bintrayRepo - name = bintrayName - desc = libraryDescription - userOrg = orgName - websiteUrl = siteUrl - vcsUrl = gitUrl - licenses = allLicenses - publish = true - publicDownloadNumbers = true - version { - desc = libraryDescription - gpg { - sign = true //Determines whether to GPG sign the files. The default is false - passphrase = _passphrase - //Optional. The passphrase for GPG signing' - } - } - } -} \ No newline at end of file diff --git a/gradle/bintray-java.gradle b/gradle/bintray-java.gradle deleted file mode 100644 index 36f97883..00000000 --- a/gradle/bintray-java.gradle +++ /dev/null @@ -1,71 +0,0 @@ -apply plugin: 'com.jfrog.bintray' - -version = libraryVersion - -task sourcesJar(type: Jar) { - from sourceSets.main.allSource - classifier = 'sources' -} - -task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' - from javadoc.destinationDir -} - -// Avoid Kotlin docs error -tasks.withType(Javadoc) { - enabled = false -} - -artifacts { - archives javadocJar - archives sourcesJar -} - -// Bintray - -def _user = System.getenv("BINTRAY_USER") -def _key = System.getenv("BINTRAY_API_KEY") -def _passphrase = System.getenv("BINTRAY_PASSPHRASE") - -if(project.rootProject.file('local.properties').exists()){ - Properties properties = new Properties() - properties.load(project.rootProject.file('local.properties').newDataInputStream()) - - def local_user = properties.getProperty("bintray.user") - if(local_user != null) _user = local_user - - def local_key = properties.getProperty("bintray.apikey") - if(local_key != null) _key = local_key - - def local_passphrase = properties.getProperty("bintray.gpg.password") - if(local_passphrase != null) _passphrase = local_passphrase -} - -bintray { - user = _user - key = _key - override = true - configurations = ['archives'] - pkg { - repo = bintrayRepo - name = bintrayName - desc = libraryDescription - userOrg = orgName - websiteUrl = siteUrl - vcsUrl = gitUrl - licenses = allLicenses - publish = true - publicDownloadNumbers = true - version { - desc = libraryDescription - gpg { - sign = true //Determines whether to GPG sign the files. The default is false - passphrase = _passphrase - //Optional. The passphrase for GPG signing' - } - } - } -} - -//from https://github.com/workarounds/bundler/blob/master/gradle/bintray-java-v1.gradle \ No newline at end of file diff --git a/gradle/install.gradle b/gradle/install.gradle deleted file mode 100644 index 78b85f3d..00000000 --- a/gradle/install.gradle +++ /dev/null @@ -1,45 +0,0 @@ -apply plugin: 'com.github.dcendents.android-maven' - -// Maven Group ID for the artifact -group = publishedGroupId - -install { - repositories.mavenInstaller { - // This generates POM.xml with proper parameters - pom { - project { - packaging 'aar' - groupId publishedGroupId - artifactId artifact - - // Add your description here - name libraryName - description libraryDescription - url siteUrl - - // Set your license - licenses { - license { - name licenseName - url licenseUrl - } - } - developers { - developer { - id developerId - name developerName - email developerEmail - } - } - scm { - connection gitUrl - developerConnection gitUrl - url siteUrl - - } - } - } - } -} - -//from https://github.com/workarounds/bundler/blob/master/gradle/install-v1.gradle \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 553356f3..953886ce 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Thu Apr 25 20:21:50 IRDT 2019 distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip +zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 index cccdd3d5..4f906e0c --- a/gradlew +++ b/gradlew @@ -1,5 +1,21 @@ #!/usr/bin/env sh +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + ############################################################################## ## ## Gradle start up script for UN*X @@ -28,7 +44,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -66,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -109,10 +126,11 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath @@ -138,19 +156,19 @@ if $cygwin ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi @@ -159,14 +177,9 @@ save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } -APP_ARGS=$(save "$@") +APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - exec "$JAVACMD" "$@" diff --git a/java-sample-app/build.gradle b/java-sample-app/build.gradle deleted file mode 100644 index 53a9be24..00000000 --- a/java-sample-app/build.gradle +++ /dev/null @@ -1,48 +0,0 @@ -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' -apply plugin: 'kotlin-kapt' - -android { - compileSdkVersion 29 - - defaultConfig { - applicationId "com.aminography.primedatepicker.javasampleapp" - minSdkVersion 14 - targetSdkVersion 29 - - versionCode 320 - versionName "3.2.0" - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - vectorDrawables.useSupportLibrary = true - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } -} - -repositories { - jcenter() -} - -dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation "com.google.android.material:material:$material_version" - implementation "androidx.appcompat:appcompat:$appcompat_version" - - // ------- PrimeDatePicker - implementation project(':library') - - // ------- PrimeCalendar - implementation "com.aminography:primecalendar:$primecalendar_version" - - // ------- Test - testImplementation "junit:junit:$junit_version" - androidTestImplementation "androidx.test.ext:junit:$androidx_junit_version" - androidTestImplementation "androidx.test.espresso:espresso-core:$androidx_espresso_version" -} diff --git a/library/build.gradle b/library/build.gradle index ee09efa7..bde66177 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -1,70 +1,36 @@ -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' -apply plugin: 'kotlin-kapt' +plugins { + id 'com.android.library' + id 'kotlin-android' + id 'kotlin-android-extensions' +} -android { - compileSdkVersion 29 +apply from: rootProject.file('scripts/android.gradle') +apply from: rootProject.file('scripts/kotlin.gradle') +android { // resourcePrefix 'pdp_' defaultConfig { - minSdkVersion 13 - targetSdkVersion 29 - - versionCode libraryVersionCode - versionName libraryVersion - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_1_8 - } -} - -repositories { - jcenter() } dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation "com.google.android.material:material:$material_version" - implementation "androidx.appcompat:appcompat:$appcompat_version" - implementation "androidx.constraintlayout:constraintlayout:$constraintlayout_version" - - // ------- Kotlin - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" + implementation dep.primecalendar + implementation dep.androidx.lifecycleKtx + implementation dep.bundles.coroutines + implementation dep.bundles.ui - // ------- PrimeCalendar - implementation "com.aminography:primecalendar:$primecalendar_version" - - // ------- Coroutine - def coroutine_version = '1.3.3' - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutine_version" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutine_version" - - // ------- Lifecycle - implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version" - - // ------- Test - testImplementation "junit:junit:$junit_version" - androidTestImplementation "androidx.test.ext:junit:$androidx_junit_version" - androidTestImplementation "androidx.test.espresso:espresso-core:$androidx_espresso_version" + testImplementation dep.junit.core + androidTestImplementation dep.bundles.androidTest } -apply from: rootProject.file('gradle/install.gradle') -apply from: rootProject.file('gradle/bintray-android.gradle') \ No newline at end of file +ext.publishInfo = [ + groupId : 'com.aminography', + artifactId : 'primedatepicker', + version : libVersion.name, + description: 'PrimeDatePicker is a wonderful date picker tool.', + githubRepo : 'PrimeDatePicker' /* https://github.com/aminography/# */ +] + +apply from: rootProject.file('scripts/publish-module.gradle') diff --git a/library/src/main/java/com/aminography/primedatepicker/calendarview/PrimeCalendarView.kt b/library/src/main/java/com/aminography/primedatepicker/calendarview/PrimeCalendarView.kt index 954d3b11..76916b50 100644 --- a/library/src/main/java/com/aminography/primedatepicker/calendarview/PrimeCalendarView.kt +++ b/library/src/main/java/com/aminography/primedatepicker/calendarview/PrimeCalendarView.kt @@ -23,20 +23,33 @@ import com.aminography.primedatepicker.calendarview.callback.IMonthViewHolderCal import com.aminography.primedatepicker.calendarview.dataholder.MonthDataHolder import com.aminography.primedatepicker.calendarview.other.StartSnapHelper import com.aminography.primedatepicker.calendarview.other.TouchControllableRecyclerView -import com.aminography.primedatepicker.common.* +import com.aminography.primedatepicker.common.BackgroundShapeType +import com.aminography.primedatepicker.common.Direction +import com.aminography.primedatepicker.common.LabelFormatter +import com.aminography.primedatepicker.common.OnDayPickedListener +import com.aminography.primedatepicker.common.OnMonthLabelClickListener +import com.aminography.primedatepicker.common.PickType import com.aminography.primedatepicker.monthview.PrimeMonthView.Companion.DEFAULT_MONTH_LABEL_FORMATTER import com.aminography.primedatepicker.monthview.PrimeMonthView.Companion.DEFAULT_WEEK_LABEL_FORMATTER import com.aminography.primedatepicker.monthview.SimpleMonthView.Companion.DEFAULT_INTERPOLATOR import com.aminography.primedatepicker.utils.DateUtils import com.aminography.primedatepicker.utils.findDirection import com.aminography.primedatepicker.utils.monthOffset -import java.util.* +import java.util.Calendar +import java.util.LinkedHashMap +import java.util.Locale /** * @author aminography */ -@Suppress("PrivatePropertyName", "MemberVisibilityCanBePrivate", "UNNECESSARY_SAFE_CALL", "unused") +@Suppress( + "NotifyDataSetChanged", + "PrivatePropertyName", + "MemberVisibilityCanBePrivate", + "UNNECESSARY_SAFE_CALL", + "unused" +) class PrimeCalendarView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, @@ -75,163 +88,163 @@ class PrimeCalendarView @JvmOverloads constructor( override var monthLabelTextColor: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var weekLabelTextColor: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var dayLabelTextColor: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var todayLabelTextColor: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var pickedDayLabelTextColor: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var pickedDayInRangeLabelTextColor: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var pickedDayBackgroundColor: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var pickedDayInRangeBackgroundColor: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var disabledDayLabelTextColor: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var adjacentMonthDayLabelTextColor: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var monthLabelTextSize: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var weekLabelTextSize: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var dayLabelTextSize: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var monthLabelTopPadding: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var monthLabelBottomPadding: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var weekLabelTopPadding: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var weekLabelBottomPadding: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var dayLabelVerticalPadding: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var pickedDayBackgroundShapeType: BackgroundShapeType = BackgroundShapeType.CIRCLE set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var pickedDayRoundSquareCornerRadius: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var showTwoWeeksInLandscape: Boolean = false set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var showAdjacentMonthDays: Boolean = false set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var animateSelection: Boolean = false set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var animationDuration: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var animationInterpolator: Interpolator = DEFAULT_INTERPOLATOR set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var monthLabelFormatter: LabelFormatter = DEFAULT_MONTH_LABEL_FORMATTER set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var weekLabelFormatter: LabelFormatter = DEFAULT_WEEK_LABEL_FORMATTER set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var toFocusDay: PrimeCalendar? = null @@ -287,25 +300,25 @@ class PrimeCalendarView @JvmOverloads constructor( override var elementPaddingLeft: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var elementPaddingRight: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var elementPaddingTop: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var elementPaddingBottom: Int = 0 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } // Programmatically Control Variables ---------------------------------------------------------- @@ -313,40 +326,40 @@ class PrimeCalendarView @JvmOverloads constructor( override var weekLabelTextColors: SparseIntArray? = null set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var typeface: Typeface? = null set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } override var pickedSingleDayCalendar: PrimeCalendar? = null set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() notifyDayPicked(true) } override var pickedRangeStartCalendar: PrimeCalendar? = null set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() notifyDayPicked(true) } override var pickedRangeEndCalendar: PrimeCalendar? = null set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() notifyDayPicked(true) } override var pickedMultipleDaysMap: LinkedHashMap? = null set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() notifyDayPicked(true) } @@ -473,14 +486,14 @@ class PrimeCalendarView @JvmOverloads constructor( } } } - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() notifyDayPicked(true) } override var firstDayOfWeek: Int = -1 set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } var calendarType = CalendarType.CIVIL @@ -503,7 +516,7 @@ class PrimeCalendarView @JvmOverloads constructor( set(value) { field = value direction = value.findDirection(calendarType) - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } var flingOrientation = FlingOrientation.VERTICAL @@ -524,7 +537,7 @@ class PrimeCalendarView @JvmOverloads constructor( override var developerOptionsShowGuideLines: Boolean = false set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } // --------------------------------------------------------------------------------------------- @@ -532,7 +545,7 @@ class PrimeCalendarView @JvmOverloads constructor( override var disabledDaysSet: MutableSet? = null set(value) { field = value - if (invalidate) adapter?.notifyDataSetChanged() + adapter?.takeIf { invalidate }?.notifyDataSetChanged() } var disabledDaysList: List = arrayListOf() @@ -556,7 +569,11 @@ class PrimeCalendarView @JvmOverloads constructor( private fun createLayoutManager(): LinearLayoutManager = when (flingOrientation) { FlingOrientation.VERTICAL -> LinearLayoutManager(context) - FlingOrientation.HORIZONTAL -> LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, direction == Direction.RTL) + FlingOrientation.HORIZONTAL -> LinearLayoutManager( + context, + LinearLayoutManager.HORIZONTAL, + direction == Direction.RTL + ) } private fun applyDividers() { @@ -599,79 +616,212 @@ class PrimeCalendarView @JvmOverloads constructor( // --------------------------------------------------------------------------------------------- init { - val layoutHeight = attrs?.getAttributeValue("http://schemas.android.com/apk/res/android", "layout_height") + val layoutHeight = + attrs?.getAttributeValue("http://schemas.android.com/apk/res/android", "layout_height") when { - layoutHeight.equals(LayoutParams.MATCH_PARENT.toString()) -> definedHeight = LayoutParams.MATCH_PARENT - layoutHeight.equals(LayoutParams.WRAP_CONTENT.toString()) -> definedHeight = LayoutParams.WRAP_CONTENT - else -> context.obtainStyledAttributes(attrs, intArrayOf(android.R.attr.layout_height)).run { - definedHeight = getDimensionPixelSize(0, LayoutParams.WRAP_CONTENT) - recycle() - } + layoutHeight.equals(LayoutParams.MATCH_PARENT.toString()) -> + definedHeight = LayoutParams.MATCH_PARENT + layoutHeight.equals(LayoutParams.WRAP_CONTENT.toString()) -> + definedHeight = LayoutParams.WRAP_CONTENT + else -> context.obtainStyledAttributes(attrs, intArrayOf(android.R.attr.layout_height)) + .run { + definedHeight = getDimensionPixelSize(0, LayoutParams.WRAP_CONTENT) + recycle() + } } - context.obtainStyledAttributes(attrs, R.styleable.PrimeCalendarView, defStyleAttr, defStyleRes).run { + context.obtainStyledAttributes( + attrs, + R.styleable.PrimeCalendarView, + defStyleAttr, + defStyleRes + ).run { doNotInvalidate { - calendarType = CalendarType.values()[getInt(R.styleable.PrimeCalendarView_calendarType, DEFAULT_CALENDAR_TYPE.ordinal)] + calendarType = CalendarType.values()[ + getInt( + R.styleable.PrimeCalendarView_calendarType, + DEFAULT_CALENDAR_TYPE.ordinal + ) + ] layoutManager = createLayoutManager() recyclerView.layoutManager = layoutManager - flingOrientation = FlingOrientation.values()[getInt(R.styleable.PrimeCalendarView_flingOrientation, DEFAULT_FLING_ORIENTATION.ordinal)] + flingOrientation = FlingOrientation.values()[ + getInt( + R.styleable.PrimeCalendarView_flingOrientation, + DEFAULT_FLING_ORIENTATION.ordinal + ) + ] - loadFactor = getInteger(R.styleable.PrimeCalendarView_loadFactor, resources.getInteger(R.integer.defaultLoadFactor)) - maxTransitionLength = getInteger(R.styleable.PrimeCalendarView_maxTransitionLength, resources.getInteger(R.integer.defaultMaxTransitionLength)) - transitionSpeedFactor = getFloat(R.styleable.PrimeCalendarView_transitionSpeedFactor, resources.getString(R.string.defaultTransitionSpeedFactor).toFloat()) + loadFactor = getInteger( + R.styleable.PrimeCalendarView_loadFactor, + resources.getInteger(R.integer.defaultLoadFactor) + ) + maxTransitionLength = getInteger( + R.styleable.PrimeCalendarView_maxTransitionLength, + resources.getInteger(R.integer.defaultMaxTransitionLength) + ) + transitionSpeedFactor = getFloat( + R.styleable.PrimeCalendarView_transitionSpeedFactor, + resources.getString(R.string.defaultTransitionSpeedFactor).toFloat() + ) - dividerColor = getColor(R.styleable.PrimeCalendarView_dividerColor, ContextCompat.getColor(context, R.color.gray400)) - dividerThickness = getDimensionPixelSize(R.styleable.PrimeCalendarView_dividerThickness, resources.getDimensionPixelSize(R.dimen.defaultDividerThickness)) - dividerInsetLeft = getDimensionPixelSize(R.styleable.PrimeCalendarView_dividerInsetLeft, resources.getDimensionPixelSize(R.dimen.defaultDividerInsetLeft)) - dividerInsetRight = getDimensionPixelSize(R.styleable.PrimeCalendarView_dividerInsetRight, resources.getDimensionPixelSize(R.dimen.defaultDividerInsetRight)) - dividerInsetTop = getDimensionPixelSize(R.styleable.PrimeCalendarView_dividerInsetTop, resources.getDimensionPixelSize(R.dimen.defaultDividerInsetTop)) - dividerInsetBottom = getDimensionPixelSize(R.styleable.PrimeCalendarView_dividerInsetBottom, resources.getDimensionPixelSize(R.dimen.defaultDividerInsetBottom)) + dividerColor = getColor( + R.styleable.PrimeCalendarView_dividerColor, + ContextCompat.getColor(context, R.color.gray400) + ) + dividerThickness = getDimensionPixelSize( + R.styleable.PrimeCalendarView_dividerThickness, + resources.getDimensionPixelSize(R.dimen.defaultDividerThickness) + ) + dividerInsetLeft = getDimensionPixelSize( + R.styleable.PrimeCalendarView_dividerInsetLeft, + resources.getDimensionPixelSize(R.dimen.defaultDividerInsetLeft) + ) + dividerInsetRight = getDimensionPixelSize( + R.styleable.PrimeCalendarView_dividerInsetRight, + resources.getDimensionPixelSize(R.dimen.defaultDividerInsetRight) + ) + dividerInsetTop = getDimensionPixelSize( + R.styleable.PrimeCalendarView_dividerInsetTop, + resources.getDimensionPixelSize(R.dimen.defaultDividerInsetTop) + ) + dividerInsetBottom = getDimensionPixelSize( + R.styleable.PrimeCalendarView_dividerInsetBottom, + resources.getDimensionPixelSize(R.dimen.defaultDividerInsetBottom) + ) - elementPaddingLeft = getDimensionPixelSize(R.styleable.PrimeCalendarView_elementPaddingLeft, resources.getDimensionPixelSize(R.dimen.defaultElementPaddingLeft)) - elementPaddingRight = getDimensionPixelSize(R.styleable.PrimeCalendarView_elementPaddingRight, resources.getDimensionPixelSize(R.dimen.defaultElementPaddingRight)) - elementPaddingTop = getDimensionPixelSize(R.styleable.PrimeCalendarView_elementPaddingTop, resources.getDimensionPixelSize(R.dimen.defaultElementPaddingTop)) - elementPaddingBottom = getDimensionPixelSize(R.styleable.PrimeCalendarView_elementPaddingBottom, resources.getDimensionPixelSize(R.dimen.defaultElementPaddingBottom)) + elementPaddingLeft = getDimensionPixelSize( + R.styleable.PrimeCalendarView_elementPaddingLeft, + resources.getDimensionPixelSize(R.dimen.defaultElementPaddingLeft) + ) + elementPaddingRight = getDimensionPixelSize( + R.styleable.PrimeCalendarView_elementPaddingRight, + resources.getDimensionPixelSize(R.dimen.defaultElementPaddingRight) + ) + elementPaddingTop = getDimensionPixelSize( + R.styleable.PrimeCalendarView_elementPaddingTop, + resources.getDimensionPixelSize(R.dimen.defaultElementPaddingTop) + ) + elementPaddingBottom = getDimensionPixelSize( + R.styleable.PrimeCalendarView_elementPaddingBottom, + resources.getDimensionPixelSize(R.dimen.defaultElementPaddingBottom) + ) // Common Attributes --------------------------------------------------------------- - monthLabelTextColor = getColor(R.styleable.PrimeCalendarView_monthLabelTextColor, ContextCompat.getColor(context, R.color.blueGray200)) - weekLabelTextColor = getColor(R.styleable.PrimeCalendarView_weekLabelTextColor, ContextCompat.getColor(context, R.color.red300)) - dayLabelTextColor = getColor(R.styleable.PrimeCalendarView_dayLabelTextColor, ContextCompat.getColor(context, R.color.gray900)) - todayLabelTextColor = getColor(R.styleable.PrimeCalendarView_todayLabelTextColor, ContextCompat.getColor(context, R.color.green400)) - pickedDayLabelTextColor = getColor(R.styleable.PrimeCalendarView_pickedDayLabelTextColor, ContextCompat.getColor(context, R.color.white)) - pickedDayInRangeLabelTextColor = getColor(R.styleable.PrimeCalendarView_pickedDayInRangeLabelTextColor, ContextCompat.getColor(context, R.color.white)) - pickedDayBackgroundColor = getColor(R.styleable.PrimeCalendarView_pickedDayBackgroundColor, ContextCompat.getColor(context, R.color.red300)) - pickedDayInRangeBackgroundColor = getColor(R.styleable.PrimeCalendarView_pickedDayInRangeBackgroundColor, ContextCompat.getColor(context, R.color.red300)) - disabledDayLabelTextColor = getColor(R.styleable.PrimeCalendarView_disabledDayLabelTextColor, ContextCompat.getColor(context, R.color.gray400)) - adjacentMonthDayLabelTextColor = getColor(R.styleable.PrimeCalendarView_adjacentMonthDayLabelTextColor, ContextCompat.getColor(context, R.color.gray400)) - - monthLabelTextSize = getDimensionPixelSize(R.styleable.PrimeCalendarView_monthLabelTextSize, resources.getDimensionPixelSize(R.dimen.defaultMonthLabelTextSize)) - weekLabelTextSize = getDimensionPixelSize(R.styleable.PrimeCalendarView_weekLabelTextSize, resources.getDimensionPixelSize(R.dimen.defaultWeekLabelTextSize)) - dayLabelTextSize = getDimensionPixelSize(R.styleable.PrimeCalendarView_dayLabelTextSize, resources.getDimensionPixelSize(R.dimen.defaultDayLabelTextSize)) - - monthLabelTopPadding = getDimensionPixelSize(R.styleable.PrimeCalendarView_monthLabelTopPadding, resources.getDimensionPixelSize(R.dimen.defaultMonthLabelTopPadding)) - monthLabelBottomPadding = getDimensionPixelSize(R.styleable.PrimeCalendarView_monthLabelBottomPadding, resources.getDimensionPixelSize(R.dimen.defaultMonthLabelBottomPadding)) - weekLabelTopPadding = getDimensionPixelSize(R.styleable.PrimeCalendarView_weekLabelTopPadding, resources.getDimensionPixelSize(R.dimen.defaultWeekLabelTopPadding)) - weekLabelBottomPadding = getDimensionPixelSize(R.styleable.PrimeCalendarView_weekLabelBottomPadding, resources.getDimensionPixelSize(R.dimen.defaultWeekLabelBottomPadding)) - dayLabelVerticalPadding = getDimensionPixelSize(R.styleable.PrimeCalendarView_dayLabelVerticalPadding, resources.getDimensionPixelSize(R.dimen.defaultDayLabelVerticalPadding)) - - pickedDayBackgroundShapeType = BackgroundShapeType.values()[getInt(R.styleable.PrimeCalendarView_pickedDayBackgroundShapeType, DEFAULT_BACKGROUND_SHAPE_TYPE.ordinal)] - pickedDayRoundSquareCornerRadius = getDimensionPixelSize(R.styleable.PrimeCalendarView_pickedDayRoundSquareCornerRadius, resources.getDimensionPixelSize(R.dimen.defaultPickedDayRoundSquareCornerRadius)) - - showTwoWeeksInLandscape = getBoolean(R.styleable.PrimeCalendarView_showTwoWeeksInLandscape, resources.getBoolean(R.bool.defaultShowTwoWeeksInLandscape)) - showAdjacentMonthDays = getBoolean(R.styleable.PrimeCalendarView_showAdjacentMonthDays, resources.getBoolean(R.bool.defaultShowAdjacentMonthDays)) - - animateSelection = getBoolean(R.styleable.PrimeCalendarView_animateSelection, resources.getBoolean(R.bool.defaultAnimateSelection)) - animationDuration = getInteger(R.styleable.PrimeCalendarView_animationDuration, resources.getInteger(R.integer.defaultAnimationDuration)) + monthLabelTextColor = getColor( + R.styleable.PrimeCalendarView_monthLabelTextColor, + ContextCompat.getColor(context, R.color.blueGray200) + ) + weekLabelTextColor = getColor( + R.styleable.PrimeCalendarView_weekLabelTextColor, + ContextCompat.getColor(context, R.color.red300) + ) + dayLabelTextColor = getColor( + R.styleable.PrimeCalendarView_dayLabelTextColor, + ContextCompat.getColor(context, R.color.gray900) + ) + todayLabelTextColor = getColor( + R.styleable.PrimeCalendarView_todayLabelTextColor, + ContextCompat.getColor(context, R.color.green400) + ) + pickedDayLabelTextColor = getColor( + R.styleable.PrimeCalendarView_pickedDayLabelTextColor, + ContextCompat.getColor(context, R.color.white) + ) + pickedDayInRangeLabelTextColor = getColor( + R.styleable.PrimeCalendarView_pickedDayInRangeLabelTextColor, + ContextCompat.getColor(context, R.color.white) + ) + pickedDayBackgroundColor = getColor( + R.styleable.PrimeCalendarView_pickedDayBackgroundColor, + ContextCompat.getColor(context, R.color.red300) + ) + pickedDayInRangeBackgroundColor = getColor( + R.styleable.PrimeCalendarView_pickedDayInRangeBackgroundColor, + ContextCompat.getColor(context, R.color.red300) + ) + disabledDayLabelTextColor = getColor( + R.styleable.PrimeCalendarView_disabledDayLabelTextColor, + ContextCompat.getColor(context, R.color.gray400) + ) + adjacentMonthDayLabelTextColor = getColor( + R.styleable.PrimeCalendarView_adjacentMonthDayLabelTextColor, + ContextCompat.getColor(context, R.color.gray400) + ) + + monthLabelTextSize = getDimensionPixelSize( + R.styleable.PrimeCalendarView_monthLabelTextSize, + resources.getDimensionPixelSize(R.dimen.defaultMonthLabelTextSize) + ) + weekLabelTextSize = getDimensionPixelSize( + R.styleable.PrimeCalendarView_weekLabelTextSize, + resources.getDimensionPixelSize(R.dimen.defaultWeekLabelTextSize) + ) + dayLabelTextSize = getDimensionPixelSize( + R.styleable.PrimeCalendarView_dayLabelTextSize, + resources.getDimensionPixelSize(R.dimen.defaultDayLabelTextSize) + ) + + monthLabelTopPadding = getDimensionPixelSize( + R.styleable.PrimeCalendarView_monthLabelTopPadding, + resources.getDimensionPixelSize(R.dimen.defaultMonthLabelTopPadding) + ) + monthLabelBottomPadding = getDimensionPixelSize( + R.styleable.PrimeCalendarView_monthLabelBottomPadding, + resources.getDimensionPixelSize(R.dimen.defaultMonthLabelBottomPadding) + ) + weekLabelTopPadding = getDimensionPixelSize( + R.styleable.PrimeCalendarView_weekLabelTopPadding, + resources.getDimensionPixelSize(R.dimen.defaultWeekLabelTopPadding) + ) + weekLabelBottomPadding = getDimensionPixelSize( + R.styleable.PrimeCalendarView_weekLabelBottomPadding, + resources.getDimensionPixelSize(R.dimen.defaultWeekLabelBottomPadding) + ) + dayLabelVerticalPadding = getDimensionPixelSize( + R.styleable.PrimeCalendarView_dayLabelVerticalPadding, + resources.getDimensionPixelSize(R.dimen.defaultDayLabelVerticalPadding) + ) + + pickedDayBackgroundShapeType = BackgroundShapeType.values()[ + getInt( + R.styleable.PrimeCalendarView_pickedDayBackgroundShapeType, + DEFAULT_BACKGROUND_SHAPE_TYPE.ordinal + ) + ] + pickedDayRoundSquareCornerRadius = getDimensionPixelSize( + R.styleable.PrimeCalendarView_pickedDayRoundSquareCornerRadius, + resources.getDimensionPixelSize(R.dimen.defaultPickedDayRoundSquareCornerRadius) + ) + + showTwoWeeksInLandscape = getBoolean( + R.styleable.PrimeCalendarView_showTwoWeeksInLandscape, + resources.getBoolean(R.bool.defaultShowTwoWeeksInLandscape) + ) + showAdjacentMonthDays = getBoolean( + R.styleable.PrimeCalendarView_showAdjacentMonthDays, + resources.getBoolean(R.bool.defaultShowAdjacentMonthDays) + ) + + animateSelection = getBoolean( + R.styleable.PrimeCalendarView_animateSelection, + resources.getBoolean(R.bool.defaultAnimateSelection) + ) + animationDuration = getInteger( + R.styleable.PrimeCalendarView_animationDuration, + resources.getInteger(R.integer.defaultAnimationDuration) + ) } recycle() } addView(recyclerView) recyclerView.speedFactor = transitionSpeedFactor - recyclerView.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) + recyclerView.layoutParams = + LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) recyclerView.addOnScrollListener(OnScrollListener()) recyclerView.setHasFixedSize(true) @@ -772,7 +922,8 @@ class PrimeCalendarView @JvmOverloads constructor( firstDayOfWeek = DateUtils.defaultWeekStartDay(calendarType) } - dataList = createPivotList(calendarType, year, month, minDateCalendar, maxDateCalendar, loadFactor) + dataList = + createPivotList(calendarType, year, month, minDateCalendar, maxDateCalendar, loadFactor) if (animate) { findFirstVisibleItem()?.let { current -> val transitionList = createTransitionList( @@ -904,7 +1055,9 @@ class PrimeCalendarView @JvmOverloads constructor( } PickType.RANGE_END -> { if (endDay != null) { - if (pickedRangeStartCalendar != null && !DateUtils.isBefore(endDay, pickedRangeStartCalendar)) { + if (pickedRangeStartCalendar != null && + !DateUtils.isBefore(endDay, pickedRangeStartCalendar) + ) { pickedRangeEndCalendar = endDay hasChanged = true } @@ -1069,79 +1222,80 @@ class PrimeCalendarView @JvmOverloads constructor( // Save/Restore States ------------------------------------------------------------------------- - override fun onSaveInstanceState(): Parcelable? { - val superState = super.onSaveInstanceState() - val savedState = SavedState(superState) - - savedState.calendarType = calendarType.ordinal - savedState.locale = locale.language - - currentItemCalendar()?.run { - savedState.currentYear = year - savedState.currentMonth = month - } - - savedState.flingOrientation = flingOrientation.ordinal - - savedState.minDateCalendar = DateUtils.storeCalendar(minDateCalendar) - savedState.maxDateCalendar = DateUtils.storeCalendar(maxDateCalendar) - - savedState.pickType = pickType.name - savedState.pickedSingleDayCalendar = DateUtils.storeCalendar(pickedSingleDayCalendar) - savedState.pickedRangeStartCalendar = DateUtils.storeCalendar(pickedRangeStartCalendar) - savedState.pickedRangeEndCalendar = DateUtils.storeCalendar(pickedRangeEndCalendar) + override fun onSaveInstanceState(): Parcelable { + return SavedState(super.onSaveInstanceState()) + .also { + it.calendarType = calendarType.ordinal + it.locale = locale.language - savedState.pickedMultipleDaysList = pickedMultipleDaysMap?.values?.map { - DateUtils.storeCalendar(it)!! - } ?: arrayListOf() - - disabledDaysSet?.let { savedState.disabledDaysList = it.toList() } - - savedState.loadFactor = loadFactor - savedState.maxTransitionLength = maxTransitionLength - savedState.transitionSpeedFactor = transitionSpeedFactor - savedState.dividerColor = dividerColor - savedState.dividerThickness = dividerThickness - savedState.dividerInsetLeft = dividerInsetLeft - savedState.dividerInsetRight = dividerInsetRight - savedState.dividerInsetTop = dividerInsetTop - savedState.dividerInsetBottom = dividerInsetBottom - - savedState.elementPaddingLeft = elementPaddingLeft - savedState.elementPaddingRight = elementPaddingRight - savedState.elementPaddingTop = elementPaddingTop - savedState.elementPaddingBottom = elementPaddingBottom - - // Common Attributes ----------------------------------------------------------------------- + currentItemCalendar()?.run { + it.currentYear = year + it.currentMonth = month + } - savedState.monthLabelTextColor = monthLabelTextColor - savedState.weekLabelTextColor = weekLabelTextColor - savedState.dayLabelTextColor = dayLabelTextColor - savedState.todayLabelTextColor = todayLabelTextColor - savedState.pickedDayLabelTextColor = pickedDayLabelTextColor - savedState.pickedDayInRangeLabelTextColor = pickedDayInRangeLabelTextColor - savedState.pickedDayBackgroundColor = pickedDayBackgroundColor - savedState.pickedDayInRangeBackgroundColor = pickedDayInRangeBackgroundColor - savedState.disabledDayLabelTextColor = disabledDayLabelTextColor - savedState.adjacentMonthDayLabelTextColor = adjacentMonthDayLabelTextColor - savedState.monthLabelTextSize = monthLabelTextSize - savedState.weekLabelTextSize = weekLabelTextSize - savedState.dayLabelTextSize = dayLabelTextSize - savedState.monthLabelTopPadding = monthLabelTopPadding - savedState.monthLabelBottomPadding = monthLabelBottomPadding - savedState.weekLabelTopPadding = weekLabelTopPadding - savedState.weekLabelBottomPadding = weekLabelBottomPadding - savedState.dayLabelVerticalPadding = dayLabelVerticalPadding - savedState.showTwoWeeksInLandscape = showTwoWeeksInLandscape - savedState.showAdjacentMonthDays = showAdjacentMonthDays - - savedState.pickedDayBackgroundShapeType = pickedDayBackgroundShapeType.ordinal - savedState.pickedDayRoundSquareCornerRadius = pickedDayRoundSquareCornerRadius - - savedState.animateSelection = animateSelection - savedState.animationDuration = animationDuration - - return savedState + it.flingOrientation = flingOrientation.ordinal + + it.minDateCalendar = DateUtils.storeCalendar(minDateCalendar) + it.maxDateCalendar = DateUtils.storeCalendar(maxDateCalendar) + + it.pickType = pickType.name + it.pickedSingleDayCalendar = + DateUtils.storeCalendar(pickedSingleDayCalendar) + it.pickedRangeStartCalendar = + DateUtils.storeCalendar(pickedRangeStartCalendar) + it.pickedRangeEndCalendar = DateUtils.storeCalendar(pickedRangeEndCalendar) + + it.pickedMultipleDaysList = pickedMultipleDaysMap + ?.values + ?.mapNotNull { day -> DateUtils.storeCalendar(day) } + ?: arrayListOf() + + disabledDaysSet?.run { it.disabledDaysList = toList() } + + it.loadFactor = loadFactor + it.maxTransitionLength = maxTransitionLength + it.transitionSpeedFactor = transitionSpeedFactor + it.dividerColor = dividerColor + it.dividerThickness = dividerThickness + it.dividerInsetLeft = dividerInsetLeft + it.dividerInsetRight = dividerInsetRight + it.dividerInsetTop = dividerInsetTop + it.dividerInsetBottom = dividerInsetBottom + + it.elementPaddingLeft = elementPaddingLeft + it.elementPaddingRight = elementPaddingRight + it.elementPaddingTop = elementPaddingTop + it.elementPaddingBottom = elementPaddingBottom + + // Common Attributes ----------------------------------------------------------------------- + + it.monthLabelTextColor = monthLabelTextColor + it.weekLabelTextColor = weekLabelTextColor + it.dayLabelTextColor = dayLabelTextColor + it.todayLabelTextColor = todayLabelTextColor + it.pickedDayLabelTextColor = pickedDayLabelTextColor + it.pickedDayInRangeLabelTextColor = pickedDayInRangeLabelTextColor + it.pickedDayBackgroundColor = pickedDayBackgroundColor + it.pickedDayInRangeBackgroundColor = pickedDayInRangeBackgroundColor + it.disabledDayLabelTextColor = disabledDayLabelTextColor + it.adjacentMonthDayLabelTextColor = adjacentMonthDayLabelTextColor + it.monthLabelTextSize = monthLabelTextSize + it.weekLabelTextSize = weekLabelTextSize + it.dayLabelTextSize = dayLabelTextSize + it.monthLabelTopPadding = monthLabelTopPadding + it.monthLabelBottomPadding = monthLabelBottomPadding + it.weekLabelTopPadding = weekLabelTopPadding + it.weekLabelBottomPadding = weekLabelBottomPadding + it.dayLabelVerticalPadding = dayLabelVerticalPadding + it.showTwoWeeksInLandscape = showTwoWeeksInLandscape + it.showAdjacentMonthDays = showAdjacentMonthDays + + it.pickedDayBackgroundShapeType = pickedDayBackgroundShapeType.ordinal + it.pickedDayRoundSquareCornerRadius = pickedDayRoundSquareCornerRadius + + it.animateSelection = animateSelection + it.animationDuration = animationDuration + } } override fun onRestoreInstanceState(state: Parcelable?) { @@ -1229,69 +1383,69 @@ class PrimeCalendarView @JvmOverloads constructor( private class SavedState : BaseSavedState { - internal var calendarType: Int = 0 - internal var locale: String? = null - internal var currentYear: Int = 0 - internal var currentMonth: Int = 0 + var calendarType: Int = 0 + var locale: String? = null + var currentYear: Int = 0 + var currentMonth: Int = 0 - internal var flingOrientation: Int = 0 + var flingOrientation: Int = 0 - internal var minDateCalendar: String? = null - internal var maxDateCalendar: String? = null + var minDateCalendar: String? = null + var maxDateCalendar: String? = null - internal var pickType: String? = null - internal var pickedSingleDayCalendar: String? = null - internal var pickedRangeStartCalendar: String? = null - internal var pickedRangeEndCalendar: String? = null - internal var pickedMultipleDaysList: List? = null + var pickType: String? = null + var pickedSingleDayCalendar: String? = null + var pickedRangeStartCalendar: String? = null + var pickedRangeEndCalendar: String? = null + var pickedMultipleDaysList: List? = null - internal var disabledDaysList: List? = null + var disabledDaysList: List? = null - internal var loadFactor: Int = 0 - internal var maxTransitionLength: Int = 0 - internal var transitionSpeedFactor: Float = 0f - internal var dividerColor: Int = 0 - internal var dividerThickness: Int = 0 - internal var dividerInsetLeft: Int = 0 - internal var dividerInsetRight: Int = 0 - internal var dividerInsetTop: Int = 0 - internal var dividerInsetBottom: Int = 0 + var loadFactor: Int = 0 + var maxTransitionLength: Int = 0 + var transitionSpeedFactor: Float = 0f + var dividerColor: Int = 0 + var dividerThickness: Int = 0 + var dividerInsetLeft: Int = 0 + var dividerInsetRight: Int = 0 + var dividerInsetTop: Int = 0 + var dividerInsetBottom: Int = 0 - internal var elementPaddingLeft: Int = 0 - internal var elementPaddingRight: Int = 0 - internal var elementPaddingTop: Int = 0 - internal var elementPaddingBottom: Int = 0 + var elementPaddingLeft: Int = 0 + var elementPaddingRight: Int = 0 + var elementPaddingTop: Int = 0 + var elementPaddingBottom: Int = 0 // Common Attributes ----------------------------------------------------------------------- - internal var monthLabelTextColor: Int = 0 - internal var weekLabelTextColor: Int = 0 - internal var dayLabelTextColor: Int = 0 - internal var todayLabelTextColor: Int = 0 - internal var pickedDayLabelTextColor: Int = 0 - internal var pickedDayInRangeLabelTextColor: Int = 0 - internal var pickedDayBackgroundColor: Int = 0 - internal var pickedDayInRangeBackgroundColor: Int = 0 - internal var disabledDayLabelTextColor: Int = 0 - internal var adjacentMonthDayLabelTextColor: Int = 0 - internal var monthLabelTextSize: Int = 0 - internal var weekLabelTextSize: Int = 0 - internal var dayLabelTextSize: Int = 0 - internal var monthLabelTopPadding: Int = 0 - internal var monthLabelBottomPadding: Int = 0 - internal var weekLabelTopPadding: Int = 0 - internal var weekLabelBottomPadding: Int = 0 - internal var dayLabelVerticalPadding: Int = 0 - internal var showTwoWeeksInLandscape: Boolean = false - internal var showAdjacentMonthDays: Boolean = false - - internal var pickedDayBackgroundShapeType: Int = 0 - internal var pickedDayRoundSquareCornerRadius: Int = 0 - - internal var animateSelection: Boolean = false - internal var animationDuration: Int = 0 - - internal constructor(superState: Parcelable?) : super(superState) + var monthLabelTextColor: Int = 0 + var weekLabelTextColor: Int = 0 + var dayLabelTextColor: Int = 0 + var todayLabelTextColor: Int = 0 + var pickedDayLabelTextColor: Int = 0 + var pickedDayInRangeLabelTextColor: Int = 0 + var pickedDayBackgroundColor: Int = 0 + var pickedDayInRangeBackgroundColor: Int = 0 + var disabledDayLabelTextColor: Int = 0 + var adjacentMonthDayLabelTextColor: Int = 0 + var monthLabelTextSize: Int = 0 + var weekLabelTextSize: Int = 0 + var dayLabelTextSize: Int = 0 + var monthLabelTopPadding: Int = 0 + var monthLabelBottomPadding: Int = 0 + var weekLabelTopPadding: Int = 0 + var weekLabelBottomPadding: Int = 0 + var dayLabelVerticalPadding: Int = 0 + var showTwoWeeksInLandscape: Boolean = false + var showAdjacentMonthDays: Boolean = false + + var pickedDayBackgroundShapeType: Int = 0 + var pickedDayRoundSquareCornerRadius: Int = 0 + + var animateSelection: Boolean = false + var animationDuration: Int = 0 + + constructor(superState: Parcelable?) : super(superState) private constructor(input: Parcel) : super(input) { calendarType = input.readInt() @@ -1437,4 +1591,4 @@ class PrimeCalendarView @JvmOverloads constructor( private val DEFAULT_FLING_ORIENTATION = FlingOrientation.VERTICAL } -} \ No newline at end of file +} diff --git a/library/src/main/java/com/aminography/primedatepicker/monthview/PrimeMonthView.kt b/library/src/main/java/com/aminography/primedatepicker/monthview/PrimeMonthView.kt index 9ccb0217..1c57c505 100644 --- a/library/src/main/java/com/aminography/primedatepicker/monthview/PrimeMonthView.kt +++ b/library/src/main/java/com/aminography/primedatepicker/monthview/PrimeMonthView.kt @@ -12,11 +12,11 @@ import androidx.annotation.AttrRes import androidx.annotation.StyleRes import androidx.core.content.ContextCompat import com.aminography.primecalendar.common.CalendarFactory +import com.aminography.primecalendar.common.localizeDigits import com.aminography.primedatepicker.R import com.aminography.primedatepicker.common.LabelFormatter import com.aminography.primedatepicker.monthview.painters.MonthLabelPainter import com.aminography.primedatepicker.monthview.painters.WeekDayLabelsPainter -import com.aminography.primedatepicker.utils.localizeDigits import java.util.* /** @@ -143,21 +143,46 @@ class PrimeMonthView @JvmOverloads constructor( // --------------------------------------------------------------------------------------------- init { - context.obtainStyledAttributes(attrs, R.styleable.PrimeMonthView, defStyleAttr, defStyleRes).run { - doNotInvalidate { - monthLabelTextColor = getColor(R.styleable.PrimeMonthView_monthLabelTextColor, ContextCompat.getColor(context, R.color.blueGray200)) - weekLabelTextColor = getColor(R.styleable.PrimeMonthView_weekLabelTextColor, ContextCompat.getColor(context, R.color.red300)) - - monthLabelTextSize = getDimensionPixelSize(R.styleable.PrimeMonthView_monthLabelTextSize, resources.getDimensionPixelSize(R.dimen.defaultMonthLabelTextSize)) - weekLabelTextSize = getDimensionPixelSize(R.styleable.PrimeMonthView_weekLabelTextSize, resources.getDimensionPixelSize(R.dimen.defaultWeekLabelTextSize)) - - monthLabelTopPadding = getDimensionPixelSize(R.styleable.PrimeMonthView_monthLabelTopPadding, resources.getDimensionPixelSize(R.dimen.defaultMonthLabelTopPadding)) - monthLabelBottomPadding = getDimensionPixelSize(R.styleable.PrimeMonthView_monthLabelBottomPadding, resources.getDimensionPixelSize(R.dimen.defaultMonthLabelBottomPadding)) - weekLabelTopPadding = getDimensionPixelSize(R.styleable.PrimeMonthView_weekLabelTopPadding, resources.getDimensionPixelSize(R.dimen.defaultWeekLabelTopPadding)) - weekLabelBottomPadding = getDimensionPixelSize(R.styleable.PrimeMonthView_weekLabelBottomPadding, resources.getDimensionPixelSize(R.dimen.defaultWeekLabelBottomPadding)) + context.obtainStyledAttributes(attrs, R.styleable.PrimeMonthView, defStyleAttr, defStyleRes) + .run { + doNotInvalidate { + monthLabelTextColor = getColor( + R.styleable.PrimeMonthView_monthLabelTextColor, + ContextCompat.getColor(context, R.color.blueGray200) + ) + weekLabelTextColor = getColor( + R.styleable.PrimeMonthView_weekLabelTextColor, + ContextCompat.getColor(context, R.color.red300) + ) + + monthLabelTextSize = getDimensionPixelSize( + R.styleable.PrimeMonthView_monthLabelTextSize, + resources.getDimensionPixelSize(R.dimen.defaultMonthLabelTextSize) + ) + weekLabelTextSize = getDimensionPixelSize( + R.styleable.PrimeMonthView_weekLabelTextSize, + resources.getDimensionPixelSize(R.dimen.defaultWeekLabelTextSize) + ) + + monthLabelTopPadding = getDimensionPixelSize( + R.styleable.PrimeMonthView_monthLabelTopPadding, + resources.getDimensionPixelSize(R.dimen.defaultMonthLabelTopPadding) + ) + monthLabelBottomPadding = getDimensionPixelSize( + R.styleable.PrimeMonthView_monthLabelBottomPadding, + resources.getDimensionPixelSize(R.dimen.defaultMonthLabelBottomPadding) + ) + weekLabelTopPadding = getDimensionPixelSize( + R.styleable.PrimeMonthView_weekLabelTopPadding, + resources.getDimensionPixelSize(R.dimen.defaultWeekLabelTopPadding) + ) + weekLabelBottomPadding = getDimensionPixelSize( + R.styleable.PrimeMonthView_weekLabelBottomPadding, + resources.getDimensionPixelSize(R.dimen.defaultWeekLabelBottomPadding) + ) + } + recycle() } - recycle() - } monthLabelPainter.also { it.monthLabelTextSize = monthLabelTextSize @@ -213,11 +238,10 @@ class PrimeMonthView @JvmOverloads constructor( override fun setupGotoExtras() { super.setupGotoExtras() - firstDayOfMonthCalendar?.let { - monthLabelFormatter(it) - }?.also { - monthLabel = it.localizeDigits(locale) - } + + firstDayOfMonthCalendar + ?.let { monthLabelFormatter(it) } + ?.let { monthLabel = it.localizeDigits(locale) } CalendarFactory.newInstance(calendarType, locale).let { weekLabels = Array(7) { dayOfWeek -> @@ -237,15 +261,17 @@ class PrimeMonthView @JvmOverloads constructor( when (event.action) { MotionEvent.ACTION_UP -> { if (!super.onTouchEvent(event)) { - isMonthTouched(event.x, event.y).takeIf { it }?.run { - val calendar = CalendarFactory.newInstance(calendarType, locale) - calendar.set(year, month, 1) - onMonthLabelClickListener?.onMonthLabelClicked( - calendar, - event.x.toInt(), - event.y.toInt() - ) - } + isMonthTouched(event.x, event.y) + .takeIf { it } + ?.run { + val calendar = CalendarFactory.newInstance(calendarType, locale) + calendar.set(year, month, 1) + onMonthLabelClickListener?.onMonthLabelClicked( + calendar, + event.x.toInt(), + event.y.toInt() + ) + } } } } @@ -266,21 +292,20 @@ class PrimeMonthView @JvmOverloads constructor( // Save/Restore States ------------------------------------------------------------------------- - override fun onSaveInstanceState(): Parcelable? { - val savedState = SavedState(super.onSaveInstanceState()) + override fun onSaveInstanceState(): Parcelable { + return SavedState(super.onSaveInstanceState()) + .also { + it.monthLabelTextColor = monthLabelTextColor + it.weekLabelTextColor = weekLabelTextColor - savedState.monthLabelTextColor = monthLabelTextColor - savedState.weekLabelTextColor = weekLabelTextColor + it.monthLabelTextSize = monthLabelTextSize + it.weekLabelTextSize = weekLabelTextSize - savedState.monthLabelTextSize = monthLabelTextSize - savedState.weekLabelTextSize = weekLabelTextSize - - savedState.monthLabelTopPadding = monthLabelTopPadding - savedState.monthLabelBottomPadding = monthLabelBottomPadding - savedState.weekLabelTopPadding = weekLabelTopPadding - savedState.weekLabelBottomPadding = weekLabelBottomPadding - - return savedState + it.monthLabelTopPadding = monthLabelTopPadding + it.monthLabelBottomPadding = monthLabelBottomPadding + it.weekLabelTopPadding = weekLabelTopPadding + it.weekLabelBottomPadding = weekLabelBottomPadding + } } override fun onRestoreInstanceState(state: Parcelable?) { @@ -304,18 +329,18 @@ class PrimeMonthView @JvmOverloads constructor( private class SavedState : BaseSavedState { - internal var monthLabelTextColor: Int = 0 - internal var weekLabelTextColor: Int = 0 + var monthLabelTextColor: Int = 0 + var weekLabelTextColor: Int = 0 - internal var monthLabelTextSize: Int = 0 - internal var weekLabelTextSize: Int = 0 + var monthLabelTextSize: Int = 0 + var weekLabelTextSize: Int = 0 - internal var monthLabelTopPadding: Int = 0 - internal var monthLabelBottomPadding: Int = 0 - internal var weekLabelTopPadding: Int = 0 - internal var weekLabelBottomPadding: Int = 0 + var monthLabelTopPadding: Int = 0 + var monthLabelBottomPadding: Int = 0 + var weekLabelTopPadding: Int = 0 + var weekLabelBottomPadding: Int = 0 - internal constructor(superState: Parcelable?) : super(superState) + constructor(superState: Parcelable?) : super(superState) private constructor(input: Parcel) : super(input) { monthLabelTextColor = input.readInt() @@ -359,4 +384,4 @@ class PrimeMonthView @JvmOverloads constructor( val DEFAULT_WEEK_LABEL_FORMATTER: LabelFormatter = { primeCalendar -> primeCalendar.weekDayNameShort } } -} \ No newline at end of file +} diff --git a/library/src/main/java/com/aminography/primedatepicker/monthview/SimpleMonthView.kt b/library/src/main/java/com/aminography/primedatepicker/monthview/SimpleMonthView.kt index ec911806..640139fb 100644 --- a/library/src/main/java/com/aminography/primedatepicker/monthview/SimpleMonthView.kt +++ b/library/src/main/java/com/aminography/primedatepicker/monthview/SimpleMonthView.kt @@ -19,12 +19,21 @@ import androidx.core.content.ContextCompat import com.aminography.primecalendar.PrimeCalendar import com.aminography.primecalendar.common.CalendarFactory import com.aminography.primecalendar.common.CalendarType +import com.aminography.primecalendar.common.localizeDigits import com.aminography.primedatepicker.R -import com.aminography.primedatepicker.common.* +import com.aminography.primedatepicker.common.BackgroundShapeType +import com.aminography.primedatepicker.common.Direction +import com.aminography.primedatepicker.common.LabelFormatter +import com.aminography.primedatepicker.common.OnDayPickedListener +import com.aminography.primedatepicker.common.OnMonthLabelClickListener +import com.aminography.primedatepicker.common.PickType import com.aminography.primedatepicker.monthview.painters.DayLabelsPainter -import com.aminography.primedatepicker.utils.* -import java.util.* -import kotlin.collections.LinkedHashMap +import com.aminography.primedatepicker.utils.DateUtils +import com.aminography.primedatepicker.utils.dp2px +import com.aminography.primedatepicker.utils.findDirection +import com.aminography.primedatepicker.utils.isDisplayLandscape +import java.util.Calendar +import java.util.Locale import kotlin.math.min @@ -439,31 +448,87 @@ open class SimpleMonthView @JvmOverloads constructor( // --------------------------------------------------------------------------------------------- init { - context.obtainStyledAttributes(attrs, R.styleable.SimpleMonthView, defStyleAttr, defStyleRes).run { + context.obtainStyledAttributes( + attrs, + R.styleable.SimpleMonthView, + defStyleAttr, + defStyleRes + ).run { doNotInvalidate { - calendarType = CalendarType.values()[getInt(R.styleable.SimpleMonthView_calendarType, DEFAULT_CALENDAR_TYPE.ordinal)] - - dayLabelTextColor = getColor(R.styleable.SimpleMonthView_dayLabelTextColor, ContextCompat.getColor(context, R.color.gray900)) - todayLabelTextColor = getColor(R.styleable.SimpleMonthView_todayLabelTextColor, ContextCompat.getColor(context, R.color.green400)) - pickedDayLabelTextColor = getColor(R.styleable.SimpleMonthView_pickedDayLabelTextColor, ContextCompat.getColor(context, R.color.white)) - pickedDayInRangeLabelTextColor = getColor(R.styleable.SimpleMonthView_pickedDayInRangeLabelTextColor, ContextCompat.getColor(context, R.color.white)) - pickedDayBackgroundColor = getColor(R.styleable.SimpleMonthView_pickedDayBackgroundColor, ContextCompat.getColor(context, R.color.red300)) - pickedDayInRangeBackgroundColor = getColor(R.styleable.SimpleMonthView_pickedDayInRangeBackgroundColor, ContextCompat.getColor(context, R.color.red300)) - disabledDayLabelTextColor = getColor(R.styleable.SimpleMonthView_disabledDayLabelTextColor, ContextCompat.getColor(context, R.color.gray400)) - adjacentMonthDayLabelTextColor = getColor(R.styleable.SimpleMonthView_adjacentMonthDayLabelTextColor, ContextCompat.getColor(context, R.color.gray400)) - - dayLabelTextSize = getDimensionPixelSize(R.styleable.SimpleMonthView_dayLabelTextSize, resources.getDimensionPixelSize(R.dimen.defaultDayLabelTextSize)) - - dayLabelVerticalPadding = getDimensionPixelSize(R.styleable.SimpleMonthView_dayLabelVerticalPadding, resources.getDimensionPixelSize(R.dimen.defaultDayLabelVerticalPadding)) - - pickedDayBackgroundShapeType = BackgroundShapeType.values()[getInt(R.styleable.SimpleMonthView_pickedDayBackgroundShapeType, DEFAULT_BACKGROUND_SHAPE_TYPE.ordinal)] - pickedDayRoundSquareCornerRadius = getDimensionPixelSize(R.styleable.SimpleMonthView_pickedDayRoundSquareCornerRadius, resources.getDimensionPixelSize(R.dimen.defaultPickedDayRoundSquareCornerRadius)) - - showTwoWeeksInLandscape = getBoolean(R.styleable.SimpleMonthView_showTwoWeeksInLandscape, resources.getBoolean(R.bool.defaultShowTwoWeeksInLandscape)) - showAdjacentMonthDays = getBoolean(R.styleable.SimpleMonthView_showAdjacentMonthDays, resources.getBoolean(R.bool.defaultShowAdjacentMonthDays)) - - animateSelection = getBoolean(R.styleable.SimpleMonthView_animateSelection, resources.getBoolean(R.bool.defaultAnimateSelection)) - animationDuration = getInteger(R.styleable.SimpleMonthView_animationDuration, resources.getInteger(R.integer.defaultAnimationDuration)) + calendarType = CalendarType.values()[getInt( + R.styleable.SimpleMonthView_calendarType, + DEFAULT_CALENDAR_TYPE.ordinal + )] + + dayLabelTextColor = getColor( + R.styleable.SimpleMonthView_dayLabelTextColor, + ContextCompat.getColor(context, R.color.gray900) + ) + todayLabelTextColor = getColor( + R.styleable.SimpleMonthView_todayLabelTextColor, + ContextCompat.getColor(context, R.color.green400) + ) + pickedDayLabelTextColor = getColor( + R.styleable.SimpleMonthView_pickedDayLabelTextColor, + ContextCompat.getColor(context, R.color.white) + ) + pickedDayInRangeLabelTextColor = getColor( + R.styleable.SimpleMonthView_pickedDayInRangeLabelTextColor, + ContextCompat.getColor(context, R.color.white) + ) + pickedDayBackgroundColor = getColor( + R.styleable.SimpleMonthView_pickedDayBackgroundColor, + ContextCompat.getColor(context, R.color.red300) + ) + pickedDayInRangeBackgroundColor = getColor( + R.styleable.SimpleMonthView_pickedDayInRangeBackgroundColor, + ContextCompat.getColor(context, R.color.red300) + ) + disabledDayLabelTextColor = getColor( + R.styleable.SimpleMonthView_disabledDayLabelTextColor, + ContextCompat.getColor(context, R.color.gray400) + ) + adjacentMonthDayLabelTextColor = getColor( + R.styleable.SimpleMonthView_adjacentMonthDayLabelTextColor, + ContextCompat.getColor(context, R.color.gray400) + ) + + dayLabelTextSize = getDimensionPixelSize( + R.styleable.SimpleMonthView_dayLabelTextSize, + resources.getDimensionPixelSize(R.dimen.defaultDayLabelTextSize) + ) + + dayLabelVerticalPadding = getDimensionPixelSize( + R.styleable.SimpleMonthView_dayLabelVerticalPadding, + resources.getDimensionPixelSize(R.dimen.defaultDayLabelVerticalPadding) + ) + + pickedDayBackgroundShapeType = BackgroundShapeType.values()[getInt( + R.styleable.SimpleMonthView_pickedDayBackgroundShapeType, + DEFAULT_BACKGROUND_SHAPE_TYPE.ordinal + )] + pickedDayRoundSquareCornerRadius = getDimensionPixelSize( + R.styleable.SimpleMonthView_pickedDayRoundSquareCornerRadius, + resources.getDimensionPixelSize(R.dimen.defaultPickedDayRoundSquareCornerRadius) + ) + + showTwoWeeksInLandscape = getBoolean( + R.styleable.SimpleMonthView_showTwoWeeksInLandscape, + resources.getBoolean(R.bool.defaultShowTwoWeeksInLandscape) + ) + showAdjacentMonthDays = getBoolean( + R.styleable.SimpleMonthView_showAdjacentMonthDays, + resources.getBoolean(R.bool.defaultShowAdjacentMonthDays) + ) + + animateSelection = getBoolean( + R.styleable.SimpleMonthView_animateSelection, + resources.getBoolean(R.bool.defaultAnimateSelection) + ) + animationDuration = getInteger( + R.styleable.SimpleMonthView_animationDuration, + resources.getInteger(R.integer.defaultAnimationDuration) + ) } recycle() } @@ -475,7 +540,8 @@ open class SimpleMonthView @JvmOverloads constructor( it.typeface = typeface it.shouldAnimateDayBackground = { dayOfMonth -> shouldAnimateDayBackground(dayOfMonth) } it.findDayState = { dayOfMonth -> findDayState(dayOfMonth) } - it.findDayLabelTextColor = { dayOfMonth, dayState -> findDayLabelTextColor(dayOfMonth, dayState) } + it.findDayLabelTextColor = + { dayOfMonth, dayState -> findDayLabelTextColor(dayOfMonth, dayState) } it.dayLabelFormatter = { dayOfMonth -> findDayLabelText(dayOfMonth) } } @@ -732,7 +798,11 @@ open class SimpleMonthView @JvmOverloads constructor( hasChanged = true } PickType.RANGE_END -> { - if (pickedRangeStartCalendar != null && !DateUtils.isBefore(calendar, pickedRangeStartCalendar)) { + if (pickedRangeStartCalendar != null && !DateUtils.isBefore( + calendar, + pickedRangeStartCalendar + ) + ) { pickedRangeEndCalendar = calendar hasChanged = true } @@ -821,48 +891,47 @@ open class SimpleMonthView @JvmOverloads constructor( // Save/Restore States ------------------------------------------------------------------------- override fun onSaveInstanceState(): Parcelable? { - val savedState = SavedState(super.onSaveInstanceState()) - - savedState.calendarType = calendarType.ordinal - savedState.firstDayOfWeek = firstDayOfWeek - savedState.locale = locale.language - - savedState.year = year - savedState.month = month + return SavedState(super.onSaveInstanceState()).also { + it.calendarType = calendarType.ordinal + it.firstDayOfWeek = firstDayOfWeek + it.locale = locale.language - savedState.minDateCalendar = DateUtils.storeCalendar(minDateCalendar) - savedState.maxDateCalendar = DateUtils.storeCalendar(maxDateCalendar) + it.year = year + it.month = month - savedState.pickType = pickType.name - savedState.pickedSingleDayCalendar = DateUtils.storeCalendar(pickedSingleDayCalendar) - savedState.pickedRangeStartCalendar = DateUtils.storeCalendar(pickedRangeStartCalendar) + it.minDateCalendar = DateUtils.storeCalendar(minDateCalendar) + it.maxDateCalendar = DateUtils.storeCalendar(maxDateCalendar) - savedState.pickedMultipleDaysList = pickedMultipleDaysMap?.values?.map { - DateUtils.storeCalendar(it)!! - } ?: arrayListOf() + it.pickType = pickType.name + it.pickedSingleDayCalendar = DateUtils.storeCalendar(pickedSingleDayCalendar) + it.pickedRangeStartCalendar = DateUtils.storeCalendar(pickedRangeStartCalendar) - disabledDaysSet?.let { savedState.disabledDaysList = it.toList() } + it.pickedMultipleDaysList = pickedMultipleDaysMap + ?.values + ?.mapNotNull { day -> DateUtils.storeCalendar(day) } + ?: arrayListOf() - savedState.dayLabelTextColor = dayLabelTextColor - savedState.todayLabelTextColor = todayLabelTextColor - savedState.pickedDayLabelTextColor = pickedDayLabelTextColor - savedState.pickedDayInRangeLabelTextColor = pickedDayInRangeLabelTextColor - savedState.pickedDayBackgroundColor = pickedDayBackgroundColor - savedState.pickedDayInRangeBackgroundColor = pickedDayInRangeBackgroundColor - savedState.disabledDayLabelTextColor = disabledDayLabelTextColor - savedState.adjacentMonthDayLabelTextColor = adjacentMonthDayLabelTextColor - savedState.dayLabelTextSize = dayLabelTextSize - savedState.dayLabelVerticalPadding = dayLabelVerticalPadding - savedState.showTwoWeeksInLandscape = showTwoWeeksInLandscape - savedState.showAdjacentMonthDays = showAdjacentMonthDays + disabledDaysSet?.run { it.disabledDaysList = toList() } - savedState.pickedDayBackgroundShapeType = pickedDayBackgroundShapeType.ordinal - savedState.pickedDayRoundSquareCornerRadius = pickedDayRoundSquareCornerRadius + it.dayLabelTextColor = dayLabelTextColor + it.todayLabelTextColor = todayLabelTextColor + it.pickedDayLabelTextColor = pickedDayLabelTextColor + it.pickedDayInRangeLabelTextColor = pickedDayInRangeLabelTextColor + it.pickedDayBackgroundColor = pickedDayBackgroundColor + it.pickedDayInRangeBackgroundColor = pickedDayInRangeBackgroundColor + it.disabledDayLabelTextColor = disabledDayLabelTextColor + it.adjacentMonthDayLabelTextColor = adjacentMonthDayLabelTextColor + it.dayLabelTextSize = dayLabelTextSize + it.dayLabelVerticalPadding = dayLabelVerticalPadding + it.showTwoWeeksInLandscape = showTwoWeeksInLandscape + it.showAdjacentMonthDays = showAdjacentMonthDays - savedState.animateSelection = animateSelection - savedState.animationDuration = animationDuration + it.pickedDayBackgroundShapeType = pickedDayBackgroundShapeType.ordinal + it.pickedDayRoundSquareCornerRadius = pickedDayRoundSquareCornerRadius - return savedState + it.animateSelection = animateSelection + it.animationDuration = animationDuration + } } override fun onRestoreInstanceState(state: Parcelable?) { @@ -882,7 +951,8 @@ open class SimpleMonthView @JvmOverloads constructor( pickType = savedState.pickType?.let { PickType.valueOf(it) } ?: PickType.NOTHING pickedSingleDayCalendar = DateUtils.restoreCalendar(savedState.pickedSingleDayCalendar) - pickedRangeStartCalendar = DateUtils.restoreCalendar(savedState.pickedRangeStartCalendar) + pickedRangeStartCalendar = + DateUtils.restoreCalendar(savedState.pickedRangeStartCalendar) pickedRangeEndCalendar = DateUtils.restoreCalendar(savedState.pickedRangeEndCalendar) linkedMapOf().apply { @@ -906,7 +976,8 @@ open class SimpleMonthView @JvmOverloads constructor( showTwoWeeksInLandscape = savedState.showTwoWeeksInLandscape showAdjacentMonthDays = savedState.showAdjacentMonthDays - pickedDayBackgroundShapeType = BackgroundShapeType.values()[savedState.pickedDayBackgroundShapeType] + pickedDayBackgroundShapeType = + BackgroundShapeType.values()[savedState.pickedDayBackgroundShapeType] pickedDayRoundSquareCornerRadius = savedState.pickedDayRoundSquareCornerRadius animateSelection = savedState.animateSelection @@ -921,119 +992,123 @@ open class SimpleMonthView @JvmOverloads constructor( private class SavedState : BaseSavedState { - internal var calendarType: Int = 0 - internal var firstDayOfWeek: Int = 0 - internal var locale: String? = null - internal var year: Int = 0 - internal var month: Int = 0 + var calendarType: Int = 0 + var firstDayOfWeek: Int = 0 + var locale: String? = null + var year: Int = 0 + var month: Int = 0 - internal var minDateCalendar: String? = null - internal var maxDateCalendar: String? = null + var minDateCalendar: String? = null + var maxDateCalendar: String? = null - internal var pickType: String? = null - internal var pickedSingleDayCalendar: String? = null - internal var pickedRangeStartCalendar: String? = null - internal var pickedRangeEndCalendar: String? = null - internal var pickedMultipleDaysList: List? = null + var pickType: String? = null + var pickedSingleDayCalendar: String? = null + var pickedRangeStartCalendar: String? = null + var pickedRangeEndCalendar: String? = null + var pickedMultipleDaysList: List? = null - internal var disabledDaysList: List? = null + var disabledDaysList: List? = null - internal var dayLabelTextColor: Int = 0 - internal var todayLabelTextColor: Int = 0 - internal var pickedDayLabelTextColor: Int = 0 - internal var pickedDayInRangeLabelTextColor: Int = 0 - internal var pickedDayBackgroundColor: Int = 0 - internal var pickedDayInRangeBackgroundColor: Int = 0 - internal var disabledDayLabelTextColor: Int = 0 - internal var adjacentMonthDayLabelTextColor: Int = 0 - internal var dayLabelTextSize: Int = 0 - internal var dayLabelVerticalPadding: Int = 0 - internal var showTwoWeeksInLandscape: Boolean = false - internal var showAdjacentMonthDays: Boolean = false + var dayLabelTextColor: Int = 0 + var todayLabelTextColor: Int = 0 + var pickedDayLabelTextColor: Int = 0 + var pickedDayInRangeLabelTextColor: Int = 0 + var pickedDayBackgroundColor: Int = 0 + var pickedDayInRangeBackgroundColor: Int = 0 + var disabledDayLabelTextColor: Int = 0 + var adjacentMonthDayLabelTextColor: Int = 0 + var dayLabelTextSize: Int = 0 + var dayLabelVerticalPadding: Int = 0 + var showTwoWeeksInLandscape: Boolean = false + var showAdjacentMonthDays: Boolean = false - internal var pickedDayBackgroundShapeType: Int = 0 - internal var pickedDayRoundSquareCornerRadius: Int = 0 + var pickedDayBackgroundShapeType: Int = 0 + var pickedDayRoundSquareCornerRadius: Int = 0 - internal var animateSelection: Boolean = false - internal var animationDuration: Int = 0 + var animateSelection: Boolean = false + var animationDuration: Int = 0 - internal constructor(superState: Parcelable?) : super(superState) + constructor(superState: Parcelable?) : super(superState) private constructor(input: Parcel) : super(input) { - calendarType = input.readInt() - firstDayOfWeek = input.readInt() - locale = input.readString() - year = input.readInt() - month = input.readInt() - - minDateCalendar = input.readString() - maxDateCalendar = input.readString() - - pickType = input.readString() - pickedSingleDayCalendar = input.readString() - pickedRangeStartCalendar = input.readString() - pickedRangeEndCalendar = input.readString() - input.readStringList(pickedMultipleDaysList ?: mutableListOf()) - - disabledDaysList?.let { input.readStringList(it) } - - dayLabelTextColor = input.readInt() - todayLabelTextColor = input.readInt() - pickedDayLabelTextColor = input.readInt() - pickedDayInRangeLabelTextColor = input.readInt() - pickedDayBackgroundColor = input.readInt() - pickedDayInRangeBackgroundColor = input.readInt() - disabledDayLabelTextColor = input.readInt() - adjacentMonthDayLabelTextColor = input.readInt() - dayLabelTextSize = input.readInt() - dayLabelVerticalPadding = input.readInt() - showTwoWeeksInLandscape = input.readInt() == 1 - showAdjacentMonthDays = input.readInt() == 1 - - pickedDayBackgroundShapeType = input.readInt() - pickedDayRoundSquareCornerRadius = input.readInt() - - animateSelection = input.readInt() == 1 - animationDuration = input.readInt() + input.run { + calendarType = readInt() + firstDayOfWeek = readInt() + locale = readString() + year = readInt() + month = readInt() + + minDateCalendar = readString() + maxDateCalendar = readString() + + pickType = readString() + pickedSingleDayCalendar = readString() + pickedRangeStartCalendar = readString() + pickedRangeEndCalendar = readString() + readStringList(pickedMultipleDaysList ?: mutableListOf()) + + disabledDaysList?.let { readStringList(it) } + + dayLabelTextColor = readInt() + todayLabelTextColor = readInt() + pickedDayLabelTextColor = readInt() + pickedDayInRangeLabelTextColor = readInt() + pickedDayBackgroundColor = readInt() + pickedDayInRangeBackgroundColor = readInt() + disabledDayLabelTextColor = readInt() + adjacentMonthDayLabelTextColor = readInt() + dayLabelTextSize = readInt() + dayLabelVerticalPadding = readInt() + showTwoWeeksInLandscape = readInt() == 1 + showAdjacentMonthDays = readInt() == 1 + + pickedDayBackgroundShapeType = readInt() + pickedDayRoundSquareCornerRadius = readInt() + + animateSelection = readInt() == 1 + animationDuration = readInt() + } } override fun writeToParcel(out: Parcel, flags: Int) { super.writeToParcel(out, flags) - out.writeInt(calendarType) - out.writeInt(firstDayOfWeek) - out.writeString(locale) - out.writeInt(year) - out.writeInt(month) - - out.writeString(minDateCalendar) - out.writeString(maxDateCalendar) - - out.writeString(pickType) - out.writeString(pickedSingleDayCalendar) - out.writeString(pickedRangeStartCalendar) - out.writeString(pickedRangeEndCalendar) - out.writeStringList(pickedMultipleDaysList) - - out.writeStringList(disabledDaysList) - - out.writeInt(dayLabelTextColor) - out.writeInt(todayLabelTextColor) - out.writeInt(pickedDayLabelTextColor) - out.writeInt(pickedDayInRangeLabelTextColor) - out.writeInt(pickedDayBackgroundColor) - out.writeInt(pickedDayInRangeBackgroundColor) - out.writeInt(disabledDayLabelTextColor) - out.writeInt(adjacentMonthDayLabelTextColor) - out.writeInt(dayLabelTextSize) - out.writeInt(dayLabelVerticalPadding) - out.writeInt(if (showTwoWeeksInLandscape) 1 else 0) - out.writeInt(if (showAdjacentMonthDays) 1 else 0) - - out.writeInt(pickedDayBackgroundShapeType) - out.writeInt(pickedDayRoundSquareCornerRadius) - - out.writeInt(if (animateSelection) 1 else 0) - out.writeInt(animationDuration) + out.run { + writeInt(calendarType) + writeInt(firstDayOfWeek) + writeString(locale) + writeInt(year) + writeInt(month) + + writeString(minDateCalendar) + writeString(maxDateCalendar) + + writeString(pickType) + writeString(pickedSingleDayCalendar) + writeString(pickedRangeStartCalendar) + writeString(pickedRangeEndCalendar) + writeStringList(pickedMultipleDaysList) + + writeStringList(disabledDaysList) + + writeInt(dayLabelTextColor) + writeInt(todayLabelTextColor) + writeInt(pickedDayLabelTextColor) + writeInt(pickedDayInRangeLabelTextColor) + writeInt(pickedDayBackgroundColor) + writeInt(pickedDayInRangeBackgroundColor) + writeInt(disabledDayLabelTextColor) + writeInt(adjacentMonthDayLabelTextColor) + writeInt(dayLabelTextSize) + writeInt(dayLabelVerticalPadding) + writeInt(if (showTwoWeeksInLandscape) 1 else 0) + writeInt(if (showAdjacentMonthDays) 1 else 0) + + writeInt(pickedDayBackgroundShapeType) + writeInt(pickedDayRoundSquareCornerRadius) + + writeInt(if (animateSelection) 1 else 0) + writeInt(animationDuration) + } } companion object { diff --git a/library/src/main/java/com/aminography/primedatepicker/picker/PrimeDatePickerImpl.kt b/library/src/main/java/com/aminography/primedatepicker/picker/PrimeDatePickerImpl.kt index fcf9422f..31f45d10 100644 --- a/library/src/main/java/com/aminography/primedatepicker/picker/PrimeDatePickerImpl.kt +++ b/library/src/main/java/com/aminography/primedatepicker/picker/PrimeDatePickerImpl.kt @@ -46,7 +46,7 @@ import java.util.* */ @Suppress("unused") internal class PrimeDatePickerImpl( - private val onDismiss: () -> Unit + private var onDismiss: (() -> Unit)? = null ) : PrimeDatePicker, OnDayPickedListener, OnMonthLabelClickListener { private lateinit var context: Context @@ -74,6 +74,7 @@ internal class PrimeDatePickerImpl( private var gotoView: BaseLazyView? = null private var direction: Direction = Direction.LTR private var typeface: Typeface? = null + private var autoSelectPickEndDay: Boolean = true private lateinit var themeFactory: ThemeFactory internal fun onCreate(context: Context, coroutineScope: CoroutineScope) { @@ -94,7 +95,14 @@ internal class PrimeDatePickerImpl( initialDateCalendar.firstDayOfWeek = it } + arguments?.getBoolean("autoSelectPickEndDay", true)?.let { + autoSelectPickEndDay = it + } + arguments?.getString("pickType")?.let { internalPickType = PickType.valueOf(it) } + arguments?.getBoolean("initiallyPickEndDay")?.takeIf { it }?.let { + internalPickType = PickType.RANGE_END + } direction = calendarType.findDirection(locale) @@ -192,7 +200,7 @@ internal class PrimeDatePickerImpl( (onDayPickCallback as? SingleDayPickCallback)?.onSingleDayPicked( calendarView.pickedSingleDayCalendar!! ) - onDismiss() + onDismiss?.invoke() } } PickType.RANGE_START, PickType.RANGE_END -> { @@ -203,7 +211,7 @@ internal class PrimeDatePickerImpl( calendarView.pickedRangeStartCalendar!!, calendarView.pickedRangeEndCalendar!! ) - onDismiss() + onDismiss?.invoke() } } PickType.MULTIPLE -> { @@ -213,7 +221,7 @@ internal class PrimeDatePickerImpl( (onDayPickCallback as? MultipleDaysPickCallback)?.onMultipleDaysPicked( calendarView.pickedMultipleDaysList ) - onDismiss() + onDismiss?.invoke() } } PickType.NOTHING -> { @@ -234,7 +242,7 @@ internal class PrimeDatePickerImpl( } } it.onPositiveButtonClick = { handleOnPositiveButtonClick(calendarView) } - it.onNegativeButtonClick = { onDismiss() } + it.onNegativeButtonClick = { onDismiss?.invoke() } it.applyTheme(themeFactory) } } @@ -290,10 +298,12 @@ internal class PrimeDatePickerImpl( } } it.onRangeEndClickListener = { - calendarView.pickType = PickType.RANGE_END - calendarView.pickedRangeEndCalendar?.let { day -> - day.firstDayOfWeek = initialDateCalendar.firstDayOfWeek - calendarView.goto(day, true) + if (calendarView.pickedRangeStartCalendar != null) { + calendarView.pickType = PickType.RANGE_END + calendarView.pickedRangeEndCalendar?.let { day -> + day.firstDayOfWeek = initialDateCalendar.firstDayOfWeek + calendarView.goto(day, true) + } } } } @@ -327,9 +337,14 @@ internal class PrimeDatePickerImpl( (selectionBarView as SingleDaySelectionBarView).pickedDay = singleDay } PickType.RANGE_START, PickType.RANGE_END -> { - (selectionBarView as RangeDaysSelectionBarView).run { - pickedRangeStartDay = startDay - pickedRangeEndDay = endDay + (selectionBarView as RangeDaysSelectionBarView).let { + it.pickedRangeStartDay = startDay + it.pickedRangeEndDay = endDay + + if (autoSelectPickEndDay && pickType == PickType.RANGE_START && endDay == null) { + it.animateBackground(false) + it.onRangeEndClickListener?.invoke() + } } } PickType.MULTIPLE -> { @@ -389,6 +404,7 @@ internal class PrimeDatePickerImpl( onDismissListener = null onDayPickCallback = null onDayPickedListener = null + onDismiss = null } override fun show(manager: FragmentManager, tag: String?) { diff --git a/library/src/main/java/com/aminography/primedatepicker/picker/builder/BaseRequestBuilder.kt b/library/src/main/java/com/aminography/primedatepicker/picker/builder/BaseRequestBuilder.kt index b9a556d4..7cf20ab9 100644 --- a/library/src/main/java/com/aminography/primedatepicker/picker/builder/BaseRequestBuilder.kt +++ b/library/src/main/java/com/aminography/primedatepicker/picker/builder/BaseRequestBuilder.kt @@ -31,7 +31,7 @@ abstract class BaseRequestBuilder } /** - * Specifies the minimum feasible date to be shown in date picker which is selectable. + * Specifies the minimum feasible date to be shown in date picker, which is selectable. * * @param minDate The [PrimeCalendar] to use as the minimum feasible date. * @@ -43,7 +43,7 @@ abstract class BaseRequestBuilder } /** - * Specifies the maximum feasible date to be shown in date picker which is selectable. + * Specifies the maximum feasible date to be shown in date picker, which is selectable. * * @param maxDate The [PrimeCalendar] to use as the maximum feasible date. * @@ -55,10 +55,10 @@ abstract class BaseRequestBuilder } /** - * Specifies the day which should be considered as start of week. + * Specifies the day that should be considered as start of the week. * - * @param firstDayOfWeek The day to use as start day of week. - * Possible values are: [Calendar.SUNDAY], [Calendar.MONDAY], and so on. + * @param firstDayOfWeek The day to use as the start day of the week. + * Possible values are: [Calendar.SUNDAY], [Calendar.MONDAY], etc. * * Note that if you specify firstDayOfWeek for the initialDate for example in * [PrimeDatePicker.bottomSheetWith], calling this function overrides it. @@ -71,7 +71,7 @@ abstract class BaseRequestBuilder } /** - * Specifies the list of disabled days which aren't selectable. + * Specifies the list of disabled days, which aren't selectable. * * @param disabledDays The list of [PrimeCalendar]s which aren't selectable. * diff --git a/library/src/main/java/com/aminography/primedatepicker/picker/builder/MultipleDaysRequestBuilder.kt b/library/src/main/java/com/aminography/primedatepicker/picker/builder/MultipleDaysRequestBuilder.kt index 1573d476..41fcb643 100644 --- a/library/src/main/java/com/aminography/primedatepicker/picker/builder/MultipleDaysRequestBuilder.kt +++ b/library/src/main/java/com/aminography/primedatepicker/picker/builder/MultipleDaysRequestBuilder.kt @@ -20,7 +20,7 @@ class MultipleDaysRequestBuilder internal constructor( ) : BaseRequestBuilder(clazz, PickType.MULTIPLE, initialDateCalendar, callback) { /** - * Specifies initially picked multiple days when the date picker is shown first time. + * Specifies initially picked multiple days when the date picker has just shown. * * @param pickedDays The list of [PrimeCalendar]s to use as the picked dates. * diff --git a/library/src/main/java/com/aminography/primedatepicker/picker/builder/RangeDaysRequestBuilder.kt b/library/src/main/java/com/aminography/primedatepicker/picker/builder/RangeDaysRequestBuilder.kt index 58a300ff..07e91872 100644 --- a/library/src/main/java/com/aminography/primedatepicker/picker/builder/RangeDaysRequestBuilder.kt +++ b/library/src/main/java/com/aminography/primedatepicker/picker/builder/RangeDaysRequestBuilder.kt @@ -19,7 +19,7 @@ class RangeDaysRequestBuilder internal constructor( ) : BaseRequestBuilder(clazz, PickType.RANGE_START, initialDateCalendar, callback) { /** - * Specifies initially picked range of days when the date picker is shown first time. + * Specifies initially picked range of days when the date picker has just shown. * * @param startDay The [PrimeCalendar] to use as the start date of picked range. * @param endDay The [PrimeCalendar] to use as the end date of picked range. @@ -32,6 +32,32 @@ class RangeDaysRequestBuilder internal constructor( return this } + /** + * Specifies initially picked start day when the date picker has just shown. + * + * @param startDay The [PrimeCalendar] to use as the start date of picked range. + * @param pickEndDay Indicates that the date picker initially starts with selecting the end of range. + * + * @return current instance of [RangeDaysRequestBuilder]. + */ + fun initiallyPickedStartDay(startDay: PrimeCalendar, pickEndDay: Boolean = true): RangeDaysRequestBuilder { + bundle.putString("pickedRangeStartCalendar", DateUtils.storeCalendar(startDay)) + bundle.putBoolean("initiallyPickEndDay", pickEndDay) + return this + } + + /** + * Specifies automatic selection of picking end day when the start day gets picked. + * + * @param autoSelect enables automatic selection if `true`, disables otherwise. + * + * @return current instance of [RangeDaysRequestBuilder]. + */ + fun autoSelectPickEndDay(autoSelect: Boolean): RangeDaysRequestBuilder { + bundle.putBoolean("autoSelectPickEndDay", autoSelect) + return this + } + // /** // * Specifies minimum length of range that can be picked. // * diff --git a/library/src/main/java/com/aminography/primedatepicker/picker/builder/SingleDayRequestBuilder.kt b/library/src/main/java/com/aminography/primedatepicker/picker/builder/SingleDayRequestBuilder.kt index 6e8b280f..9b21be3b 100644 --- a/library/src/main/java/com/aminography/primedatepicker/picker/builder/SingleDayRequestBuilder.kt +++ b/library/src/main/java/com/aminography/primedatepicker/picker/builder/SingleDayRequestBuilder.kt @@ -19,7 +19,7 @@ class SingleDayRequestBuilder internal constructor( ) : BaseRequestBuilder(clazz, PickType.SINGLE, initialDateCalendar, callback) { /** - * Specifies initially picked day when the date picker is shown first time. + * Specifies initially picked day when the date picker has just shown. * * @param pickedDay The [PrimeCalendar] to use as the picked date. * diff --git a/library/src/main/java/com/aminography/primedatepicker/picker/component/TwoLinesTextView.kt b/library/src/main/java/com/aminography/primedatepicker/picker/component/TwoLinesTextView.kt index 4646fd47..748655c7 100644 --- a/library/src/main/java/com/aminography/primedatepicker/picker/component/TwoLinesTextView.kt +++ b/library/src/main/java/com/aminography/primedatepicker/picker/component/TwoLinesTextView.kt @@ -261,7 +261,7 @@ internal class TwoLinesTextView @JvmOverloads constructor( // Save/Restore States ------------------------------------------------------------------------- - override fun onSaveInstanceState(): Parcelable? { + override fun onSaveInstanceState(): Parcelable { val superState = super.onSaveInstanceState() val savedState = SavedState(superState) @@ -298,16 +298,16 @@ internal class TwoLinesTextView @JvmOverloads constructor( private class SavedState : BaseSavedState { - internal var topLabelText: String = "" - internal var bottomLabelText: String = "" - internal var topLabelTextColor: Int = 0 - internal var bottomLabelTextColor: Int = 0 - internal var topLabelTextSize: Int = 0 - internal var bottomLabelTextSize: Int = 0 - internal var preferredMinWidth: Int = 0 - internal var gapBetweenLines: Int = 0 + var topLabelText: String = "" + var bottomLabelText: String = "" + var topLabelTextColor: Int = 0 + var bottomLabelTextColor: Int = 0 + var topLabelTextSize: Int = 0 + var bottomLabelTextSize: Int = 0 + var preferredMinWidth: Int = 0 + var gapBetweenLines: Int = 0 - internal constructor(superState: Parcelable?) : super(superState) + constructor(superState: Parcelable?) : super(superState) private constructor(input: Parcel) : super(input) { topLabelText = input.readString() ?: "" diff --git a/library/src/main/java/com/aminography/primedatepicker/picker/dialog/PrimeDatePickerBottomSheet.kt b/library/src/main/java/com/aminography/primedatepicker/picker/dialog/PrimeDatePickerBottomSheet.kt index 2499a0f9..30712d70 100644 --- a/library/src/main/java/com/aminography/primedatepicker/picker/dialog/PrimeDatePickerBottomSheet.kt +++ b/library/src/main/java/com/aminography/primedatepicker/picker/dialog/PrimeDatePickerBottomSheet.kt @@ -11,6 +11,7 @@ import com.aminography.primedatepicker.picker.PrimeDatePicker import com.aminography.primedatepicker.picker.PrimeDatePickerImpl import com.aminography.primedatepicker.picker.base.BaseBottomSheetDialogFragment import com.aminography.primedatepicker.picker.callback.BaseDayPickCallback +import com.aminography.primedatepicker.utils.enableHardwareAcceleration /** * `PrimeDatePickerBottomSheet` contains the logic of picking days in a bottom sheet view. @@ -29,6 +30,7 @@ internal class PrimeDatePickerBottomSheet : BaseBottomSheetDialogFragment( override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) primeDatePicker.onCreate(requireContext(), lifecycleScope) + activity?.enableHardwareAcceleration() } override fun onInitViews(rootView: View) { @@ -65,5 +67,4 @@ internal class PrimeDatePickerBottomSheet : BaseBottomSheetDialogFragment( override fun setOnEachDayPickedListener(listener: OnDayPickedListener?) { primeDatePicker.setOnEachDayPickedListener(listener) } - } diff --git a/library/src/main/java/com/aminography/primedatepicker/picker/dialog/PrimeDatePickerDialog.kt b/library/src/main/java/com/aminography/primedatepicker/picker/dialog/PrimeDatePickerDialog.kt index 6d6b2019..e06d2fcd 100644 --- a/library/src/main/java/com/aminography/primedatepicker/picker/dialog/PrimeDatePickerDialog.kt +++ b/library/src/main/java/com/aminography/primedatepicker/picker/dialog/PrimeDatePickerDialog.kt @@ -11,6 +11,7 @@ import com.aminography.primedatepicker.picker.PrimeDatePicker import com.aminography.primedatepicker.picker.PrimeDatePickerImpl import com.aminography.primedatepicker.picker.base.BaseDialogFragment import com.aminography.primedatepicker.picker.callback.BaseDayPickCallback +import com.aminography.primedatepicker.utils.enableHardwareAcceleration /** * `PrimeDatePickerBottomSheet` contains the logic of picking days in a dialog view. @@ -29,6 +30,7 @@ internal class PrimeDatePickerDialog : BaseDialogFragment( override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) primeDatePicker.onCreate(requireContext(), lifecycleScope) + activity?.enableHardwareAcceleration() } override fun onInitViews(rootView: View) { @@ -65,5 +67,4 @@ internal class PrimeDatePickerDialog : BaseDialogFragment( override fun setOnEachDayPickedListener(listener: OnDayPickedListener?) { primeDatePicker.setOnEachDayPickedListener(listener) } - } diff --git a/library/src/main/java/com/aminography/primedatepicker/picker/go/GotoView.kt b/library/src/main/java/com/aminography/primedatepicker/picker/go/GotoView.kt index be9fa49f..b223710a 100644 --- a/library/src/main/java/com/aminography/primedatepicker/picker/go/GotoView.kt +++ b/library/src/main/java/com/aminography/primedatepicker/picker/go/GotoView.kt @@ -7,11 +7,11 @@ import android.view.ViewStub import android.widget.FrameLayout import android.widget.NumberPicker import com.aminography.primecalendar.PrimeCalendar +import com.aminography.primecalendar.common.localizeDigits import com.aminography.primedatepicker.R import com.aminography.primedatepicker.common.Direction import com.aminography.primedatepicker.picker.base.BaseLazyView import com.aminography.primedatepicker.picker.component.ColoredNumberPicker -import com.aminography.primedatepicker.utils.localizeDigits import kotlinx.android.synthetic.main.goto_container.view.* /** diff --git a/library/src/main/java/com/aminography/primedatepicker/picker/selection/multiple/dataholder/PickedDayDataHolder.kt b/library/src/main/java/com/aminography/primedatepicker/picker/selection/multiple/dataholder/PickedDayDataHolder.kt index f196c415..16c52b40 100644 --- a/library/src/main/java/com/aminography/primedatepicker/picker/selection/multiple/dataholder/PickedDayDataHolder.kt +++ b/library/src/main/java/com/aminography/primedatepicker/picker/selection/multiple/dataholder/PickedDayDataHolder.kt @@ -1,8 +1,8 @@ package com.aminography.primedatepicker.picker.selection.multiple.dataholder import com.aminography.primecalendar.PrimeCalendar +import com.aminography.primecalendar.common.localizeDigits import com.aminography.primedatepicker.common.LabelFormatter -import com.aminography.primedatepicker.utils.localizeDigits /** * @author aminography @@ -14,7 +14,9 @@ internal data class PickedDayDataHolder( private val bottomLabelFormatter: LabelFormatter? ) : BasePickedDayDataHolder(id) { - val topLabel: String = topLabelFormatter?.invoke(calendar)?.localizeDigits(calendar.locale) ?: "" - val bottomLabel: String = bottomLabelFormatter?.invoke(calendar)?.localizeDigits(calendar.locale) ?: "" + val topLabel: String = topLabelFormatter?.invoke(calendar)?.localizeDigits(calendar.locale) + ?: "" + val bottomLabel: String = bottomLabelFormatter?.invoke(calendar)?.localizeDigits(calendar.locale) + ?: "" } \ No newline at end of file diff --git a/library/src/main/java/com/aminography/primedatepicker/picker/selection/range/RangeDaysSelectionBarView.kt b/library/src/main/java/com/aminography/primedatepicker/picker/selection/range/RangeDaysSelectionBarView.kt index 387a8f6d..e533c359 100644 --- a/library/src/main/java/com/aminography/primedatepicker/picker/selection/range/RangeDaysSelectionBarView.kt +++ b/library/src/main/java/com/aminography/primedatepicker/picker/selection/range/RangeDaysSelectionBarView.kt @@ -7,6 +7,7 @@ import android.view.ViewStub import android.view.animation.OvershootInterpolator import androidx.core.widget.ImageViewCompat import com.aminography.primecalendar.PrimeCalendar +import com.aminography.primecalendar.common.localizeDigits import com.aminography.primedatepicker.R import com.aminography.primedatepicker.common.Direction import com.aminography.primedatepicker.common.LabelFormatter @@ -14,7 +15,6 @@ import com.aminography.primedatepicker.common.PickType import com.aminography.primedatepicker.picker.base.BaseLazyView import com.aminography.primedatepicker.picker.selection.SelectionBarView import com.aminography.primedatepicker.utils.forceLocaleStrings -import com.aminography.primedatepicker.utils.localizeDigits import kotlinx.android.synthetic.main.selection_bar_range_days_container.view.* import java.util.* @@ -101,12 +101,14 @@ internal class RangeDaysSelectionBarView( set(value) { field = value rootView.rangeEndBackView.setOnClickListener { - animateBackground(false) - value?.invoke() + if (pickedRangeStartDay != null) { + animateBackground(false) + value?.invoke() + } } } - private fun animateBackground(isStart: Boolean, duration: Long = 300) { + internal fun animateBackground(isStart: Boolean, duration: Long = 300) { rootView.backImageView.post { ObjectAnimator.ofFloat( rootView.backImageView, @@ -122,5 +124,4 @@ internal class RangeDaysSelectionBarView( } } } - } \ No newline at end of file diff --git a/library/src/main/java/com/aminography/primedatepicker/picker/selection/single/SingleDaySelectionBarView.kt b/library/src/main/java/com/aminography/primedatepicker/picker/selection/single/SingleDaySelectionBarView.kt index 02479a55..5fde1f3c 100644 --- a/library/src/main/java/com/aminography/primedatepicker/picker/selection/single/SingleDaySelectionBarView.kt +++ b/library/src/main/java/com/aminography/primedatepicker/picker/selection/single/SingleDaySelectionBarView.kt @@ -3,12 +3,12 @@ package com.aminography.primedatepicker.picker.selection.single import android.graphics.Typeface import android.view.ViewStub import com.aminography.primecalendar.PrimeCalendar +import com.aminography.primecalendar.common.localizeDigits import com.aminography.primedatepicker.R import com.aminography.primedatepicker.common.LabelFormatter import com.aminography.primedatepicker.picker.base.BaseLazyView import com.aminography.primedatepicker.picker.selection.SelectionBarView import com.aminography.primedatepicker.utils.forceLocaleStrings -import com.aminography.primedatepicker.utils.localizeDigits import kotlinx.android.synthetic.main.selection_bar_single_day_container.view.* import java.util.* diff --git a/library/src/main/java/com/aminography/primedatepicker/utils/DateUtils.kt b/library/src/main/java/com/aminography/primedatepicker/utils/DateUtils.kt index 747cd670..b20dc3fd 100644 --- a/library/src/main/java/com/aminography/primedatepicker/utils/DateUtils.kt +++ b/library/src/main/java/com/aminography/primedatepicker/utils/DateUtils.kt @@ -24,7 +24,7 @@ object DateUtils { year == calendar.year && month == calendar.month && dayOfMonth == calendar.dayOfMonth fun isSame(first: PrimeCalendar, second: PrimeCalendar) = - first.year == second.year && first.month == second.month && first.dayOfMonth == second.dayOfMonth + first.run { isSame(year, month, dayOfMonth, second) } fun isBetweenExclusive(year: Int, month: Int, dayOfMonth: Int, start: PrimeCalendar, end: PrimeCalendar): Boolean { val offset = year * 12 + month @@ -48,11 +48,7 @@ object DateUtils { } ?: false fun isBefore(calendar: PrimeCalendar, target: PrimeCalendar?): Boolean = - target?.let { - calendar.year < it.year || - (calendar.year == it.year && calendar.month < it.month) || - (calendar.year == it.year && calendar.month == it.month && calendar.dayOfMonth < it.dayOfMonth) - } ?: false + calendar.run { isBefore(year, month, dayOfMonth, target) } fun isAfter(year: Int, month: Int, dayOfMonth: Int, target: PrimeCalendar?): Boolean = target?.let { @@ -62,11 +58,7 @@ object DateUtils { } ?: false fun isAfter(calendar: PrimeCalendar, target: PrimeCalendar?): Boolean = - target?.let { - calendar.year > it.year || - (calendar.year == it.year && calendar.month > it.month) || - (calendar.year == it.year && calendar.month == it.month && calendar.dayOfMonth > it.dayOfMonth) - } ?: false + calendar.run { isAfter(year, month, dayOfMonth, target) } fun isOutOfRange(year: Int, month: Int, dayOfMonth: Int, minDateCalendar: PrimeCalendar?, maxDateCalendar: PrimeCalendar?): Boolean = isBefore(year, month, dayOfMonth, minDateCalendar) || isAfter(year, month, dayOfMonth, maxDateCalendar) @@ -134,4 +126,4 @@ object DateUtils { } } -} \ No newline at end of file +} diff --git a/library/src/main/java/com/aminography/primedatepicker/utils/LanguageUtils.kt b/library/src/main/java/com/aminography/primedatepicker/utils/LanguageUtils.kt index 3273dbb5..a651749a 100644 --- a/library/src/main/java/com/aminography/primedatepicker/utils/LanguageUtils.kt +++ b/library/src/main/java/com/aminography/primedatepicker/utils/LanguageUtils.kt @@ -33,49 +33,4 @@ fun Locale.findDirection(calendarType: CalendarType): Direction = CalendarType.HIJRI -> Direction.RTL } else -> Direction.LTR - } - -fun String.localizeDigits(locale: Locale): String = - when (locale.language) { - PersianCalendar.DEFAULT_LOCALE, - HijriCalendar.DEFAULT_LOCALE -> withPersianDigits - else -> this - } - -fun Int.localizeDigits(locale: Locale): String = - when (locale.language) { - PersianCalendar.DEFAULT_LOCALE, - HijriCalendar.DEFAULT_LOCALE -> withPersianDigits - else -> "$this" - } - -val String.withPersianDigits: String - get() = StringBuilder().also { - for (c in toCharArray()) { - if (Character.isDigit(c)) - it.append(PERSIAN_DIGITS["$c".toInt()]) - else it.append(c) - } - }.toString() - -val Int.withPersianDigits: String - get() = StringBuilder().also { - for (c in "$this".toCharArray()) { - if (Character.isDigit(c)) - it.append(PERSIAN_DIGITS["$c".toInt()]) - else it.append(c) - } - }.toString() - -private val PERSIAN_DIGITS = charArrayOf( - '0' + 1728, - '1' + 1728, - '2' + 1728, - '3' + 1728, - '4' + 1728, - '5' + 1728, - '6' + 1728, - '7' + 1728, - '8' + 1728, - '9' + 1728 -) + } \ No newline at end of file diff --git a/library/src/main/java/com/aminography/primedatepicker/utils/ViewUtils.kt b/library/src/main/java/com/aminography/primedatepicker/utils/ViewUtils.kt index 447a1ca0..5b191e41 100644 --- a/library/src/main/java/com/aminography/primedatepicker/utils/ViewUtils.kt +++ b/library/src/main/java/com/aminography/primedatepicker/utils/ViewUtils.kt @@ -1,9 +1,11 @@ package com.aminography.primedatepicker.utils +import android.app.Activity import android.graphics.drawable.Drawable import android.graphics.drawable.GradientDrawable import android.os.Build import android.view.View +import android.view.WindowManager import androidx.core.graphics.ColorUtils import kotlinx.android.synthetic.main.fragment_date_picker_bottom_sheet.view.* @@ -44,3 +46,10 @@ fun generateTopGradientDrawable(color: Int): Drawable { ) ) } + +fun Activity.enableHardwareAcceleration() { + window.setFlags( + WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, + WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED + ) +} diff --git a/library/src/main/res/layout/action_bar_container.xml b/library/src/main/res/layout/action_bar_container.xml index bcf74428..0fbd5706 100644 --- a/library/src/main/res/layout/action_bar_container.xml +++ b/library/src/main/res/layout/action_bar_container.xml @@ -21,9 +21,9 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/material_size_12" - android:paddingStart="@dimen/material_size_12" + android:paddingLeft="@dimen/material_size_12" android:paddingTop="@dimen/material_size_8" - android:paddingEnd="@dimen/material_size_12" + android:paddingRight="@dimen/material_size_12" android:paddingBottom="@dimen/material_size_8" app:bottomLabelTextSize="0dp" app:layout_constraintBottom_toBottomOf="parent" @@ -48,9 +48,9 @@ android:id="@+id/negativeTwoLineTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:paddingStart="@dimen/material_size_12" + android:paddingLeft="@dimen/material_size_12" android:paddingTop="@dimen/material_size_8" - android:paddingEnd="@dimen/material_size_12" + android:paddingRight="@dimen/material_size_12" android:paddingBottom="@dimen/material_size_8" app:bottomLabelTextSize="0dp" app:layout_constraintBottom_toBottomOf="parent" @@ -76,9 +76,9 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="@dimen/material_size_12" - android:paddingStart="@dimen/material_size_12" + android:paddingLeft="@dimen/material_size_12" android:paddingTop="@dimen/material_size_8" - android:paddingEnd="@dimen/material_size_12" + android:paddingRight="@dimen/material_size_12" android:paddingBottom="@dimen/material_size_8" app:bottomLabelTextSize="0dp" app:layout_constraintBottom_toBottomOf="parent" diff --git a/library/src/main/res/layout/action_bar_container_rtl.xml b/library/src/main/res/layout/action_bar_container_rtl.xml index c46a5032..af543d55 100644 --- a/library/src/main/res/layout/action_bar_container_rtl.xml +++ b/library/src/main/res/layout/action_bar_container_rtl.xml @@ -21,9 +21,9 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="@dimen/material_size_12" - android:paddingStart="@dimen/material_size_12" + android:paddingLeft="@dimen/material_size_12" android:paddingTop="@dimen/material_size_8" - android:paddingEnd="@dimen/material_size_12" + android:paddingRight="@dimen/material_size_12" android:paddingBottom="@dimen/material_size_8" app:bottomLabelTextSize="0dp" app:layout_constraintBottom_toBottomOf="parent" @@ -48,9 +48,9 @@ android:id="@+id/negativeTwoLineTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:paddingStart="@dimen/material_size_12" + android:paddingLeft="@dimen/material_size_12" android:paddingTop="@dimen/material_size_8" - android:paddingEnd="@dimen/material_size_12" + android:paddingRight="@dimen/material_size_12" android:paddingBottom="@dimen/material_size_8" app:bottomLabelTextSize="0dp" app:layout_constraintBottom_toBottomOf="parent" @@ -76,9 +76,9 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/material_size_12" - android:paddingStart="@dimen/material_size_12" + android:paddingLeft="@dimen/material_size_12" android:paddingTop="@dimen/material_size_8" - android:paddingEnd="@dimen/material_size_12" + android:paddingRight="@dimen/material_size_12" android:paddingBottom="@dimen/material_size_8" app:bottomLabelTextSize="0dp" app:layout_constraintBottom_toBottomOf="parent" diff --git a/library/src/main/res/layout/fragment_date_picker_bottom_sheet.xml b/library/src/main/res/layout/fragment_date_picker_bottom_sheet.xml index 66fe6b70..e8f92e8f 100644 --- a/library/src/main/res/layout/fragment_date_picker_bottom_sheet.xml +++ b/library/src/main/res/layout/fragment_date_picker_bottom_sheet.xml @@ -29,10 +29,10 @@ android:id="@+id/selectionBarLayout" android:layout_width="0dp" android:layout_height="wrap_content" - android:paddingStart="8dp" - android:paddingTop="4dp" - android:paddingEnd="8dp" - android:paddingBottom="2dp" + android:paddingLeft="@dimen/material_size_8" + android:paddingTop="@dimen/material_size_4" + android:paddingRight="@dimen/material_size_8" + android:paddingBottom="@dimen/material_size_2" app:layout_constraintBottom_toTopOf="@id/calendarView" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/library/src/main/res/layout/fragment_date_picker_dialog.xml b/library/src/main/res/layout/fragment_date_picker_dialog.xml index cb2eb45a..97d8bab6 100644 --- a/library/src/main/res/layout/fragment_date_picker_dialog.xml +++ b/library/src/main/res/layout/fragment_date_picker_dialog.xml @@ -19,10 +19,10 @@ android:id="@+id/selectionBarLayout" android:layout_width="0dp" android:layout_height="wrap_content" - android:paddingStart="8dp" + android:paddingLeft="@dimen/material_size_8" android:paddingTop="8dp" android:paddingBottom="2dp" - android:paddingEnd="8dp" + android:paddingRight="@dimen/material_size_8" app:layout_constraintBottom_toTopOf="@id/calendarView" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/library/src/main/res/layout/goto_container.xml b/library/src/main/res/layout/goto_container.xml index a32d794b..86f40d22 100644 --- a/library/src/main/res/layout/goto_container.xml +++ b/library/src/main/res/layout/goto_container.xml @@ -55,9 +55,9 @@ android:id="@+id/closeButtonImageView" android:layout_width="48dp" android:layout_height="48dp" - android:layout_marginStart="@dimen/material_size_16" + android:layout_marginLeft="@dimen/material_size_16" android:layout_marginTop="@dimen/material_size_8" - android:layout_marginEnd="@dimen/material_size_16" + android:layout_marginRight="@dimen/material_size_16" android:alpha="0.67" android:paddingTop="@dimen/material_size_8" android:paddingBottom="@dimen/material_size_8" @@ -80,8 +80,8 @@ android:id="@+id/goButtonImageView" android:layout_width="48dp" android:layout_height="48dp" - android:layout_marginStart="@dimen/material_size_16" - android:layout_marginEnd="@dimen/material_size_16" + android:layout_marginLeft="@dimen/material_size_16" + android:layout_marginRight="@dimen/material_size_16" android:layout_marginBottom="@dimen/material_size_4" android:alpha="0.67" android:paddingTop="@dimen/material_size_8" diff --git a/library/src/main/res/layout/goto_container_rtl.xml b/library/src/main/res/layout/goto_container_rtl.xml index 7e959278..412ab393 100644 --- a/library/src/main/res/layout/goto_container_rtl.xml +++ b/library/src/main/res/layout/goto_container_rtl.xml @@ -55,9 +55,9 @@ android:id="@+id/closeButtonImageView" android:layout_width="48dp" android:layout_height="48dp" - android:layout_marginStart="@dimen/material_size_16" + android:layout_marginLeft="@dimen/material_size_16" android:layout_marginTop="@dimen/material_size_8" - android:layout_marginEnd="@dimen/material_size_16" + android:layout_marginRight="@dimen/material_size_16" android:alpha="0.67" android:paddingTop="@dimen/material_size_8" android:paddingBottom="@dimen/material_size_8" @@ -80,8 +80,8 @@ android:id="@+id/goButtonImageView" android:layout_width="48dp" android:layout_height="48dp" - android:layout_marginStart="@dimen/material_size_16" - android:layout_marginEnd="@dimen/material_size_16" + android:layout_marginLeft="@dimen/material_size_16" + android:layout_marginRight="@dimen/material_size_16" android:layout_marginBottom="@dimen/material_size_4" android:alpha="0.67" android:paddingTop="@dimen/material_size_8" diff --git a/library/src/main/res/layout/list_item_picked_day.xml b/library/src/main/res/layout/list_item_picked_day.xml index eab35817..28124787 100644 --- a/library/src/main/res/layout/list_item_picked_day.xml +++ b/library/src/main/res/layout/list_item_picked_day.xml @@ -18,9 +18,9 @@ android:id="@+id/twoLineTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:paddingStart="@dimen/material_size_8" + android:paddingLeft="@dimen/material_size_8" android:paddingTop="@dimen/material_size_4" - android:paddingEnd="@dimen/material_size_8" + android:paddingRight="@dimen/material_size_8" android:paddingBottom="@dimen/material_size_4" app:bottomLabelTextColor="@color/white" app:bottomLabelTextSize="@dimen/text_size_header_multi_small" diff --git a/library/src/main/res/layout/list_item_picked_day_empty.xml b/library/src/main/res/layout/list_item_picked_day_empty.xml index 05ba0172..3086325f 100644 --- a/library/src/main/res/layout/list_item_picked_day_empty.xml +++ b/library/src/main/res/layout/list_item_picked_day_empty.xml @@ -17,9 +17,9 @@ android:id="@+id/twoLineTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:paddingStart="@dimen/material_size_8" + android:paddingLeft="@dimen/material_size_8" android:paddingTop="@dimen/material_size_4" - android:paddingEnd="@dimen/material_size_8" + android:paddingRight="@dimen/material_size_8" android:paddingBottom="@dimen/material_size_4" app:bottomLabelTextColor="@color/transparent" app:bottomLabelTextSize="@dimen/text_size_header_multi_small" diff --git a/library/src/main/res/layout/selection_bar_multiple_days_container.xml b/library/src/main/res/layout/selection_bar_multiple_days_container.xml index 6ec0ef64..14a192f8 100644 --- a/library/src/main/res/layout/selection_bar_multiple_days_container.xml +++ b/library/src/main/res/layout/selection_bar_multiple_days_container.xml @@ -26,13 +26,14 @@ android:clipChildren="false" android:clipToPadding="true" android:fadingEdgeLength="@dimen/material_size_2" - android:paddingStart="@dimen/material_size_4" - android:paddingEnd="@dimen/material_size_4" + android:paddingLeft="@dimen/material_size_4" + android:paddingRight="@dimen/material_size_4" android:requiresFadingEdge="horizontal" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" - tools:listitem="@layout/list_item_picked_day" /> + tools:listitem="@layout/list_item_picked_day" + tools:targetApi="ice_cream_sandwich" /> \ No newline at end of file diff --git a/library/src/main/res/layout/selection_bar_range_days_container.xml b/library/src/main/res/layout/selection_bar_range_days_container.xml index 417d9d4a..c6b49dc6 100644 --- a/library/src/main/res/layout/selection_bar_range_days_container.xml +++ b/library/src/main/res/layout/selection_bar_range_days_container.xml @@ -47,9 +47,9 @@ android:layout_gravity="center" android:layout_marginStart="@dimen/material_size_4" android:layout_marginLeft="@dimen/material_size_4" - android:paddingStart="@dimen/material_size_8" + android:paddingLeft="@dimen/material_size_8" android:paddingTop="@dimen/material_size_4" - android:paddingEnd="@dimen/material_size_8" + android:paddingRight="@dimen/material_size_8" android:paddingBottom="@dimen/material_size_4" app:topLabelText="@string/prime_date_picker_from" app:topLabelTextColor="@color/white" @@ -69,9 +69,9 @@ android:layout_gravity="center" android:layout_marginEnd="@dimen/material_size_4" android:layout_marginRight="@dimen/material_size_4" - android:paddingStart="@dimen/material_size_8" + android:paddingLeft="@dimen/material_size_8" android:paddingTop="@dimen/material_size_4" - android:paddingEnd="@dimen/material_size_8" + android:paddingRight="@dimen/material_size_8" android:paddingBottom="@dimen/material_size_4" app:topLabelText="@string/prime_date_picker_to" app:topLabelTextColor="@color/white" diff --git a/library/src/main/res/layout/selection_bar_range_days_container_rtl.xml b/library/src/main/res/layout/selection_bar_range_days_container_rtl.xml index 8ba8a44a..a0ca9430 100644 --- a/library/src/main/res/layout/selection_bar_range_days_container_rtl.xml +++ b/library/src/main/res/layout/selection_bar_range_days_container_rtl.xml @@ -47,20 +47,20 @@ android:layout_gravity="center" android:layout_marginEnd="@dimen/material_size_4" android:layout_marginRight="@dimen/material_size_4" - android:paddingStart="@dimen/material_size_8" + android:paddingLeft="@dimen/material_size_8" android:paddingTop="@dimen/material_size_4" - android:paddingEnd="@dimen/material_size_8" + android:paddingRight="@dimen/material_size_8" android:paddingBottom="@dimen/material_size_4" - app:topLabelText="@string/prime_date_picker_from" - app:topLabelTextColor="@color/white" - app:topLabelTextSize="@dimen/text_size_small" + app:bottomLabelTextColor="@color/white" + app:bottomLabelTextSize="@dimen/text_size_normal" app:gapBetweenLines="@dimen/defaultGapBetweenLines" app:layout_constraintBottom_toBottomOf="@id/rangeStartBackView" app:layout_constraintEnd_toEndOf="@id/rangeStartBackView" app:layout_constraintStart_toStartOf="@id/rangeStartBackView" app:layout_constraintTop_toTopOf="@id/rangeStartBackView" - app:bottomLabelTextColor="@color/white" - app:bottomLabelTextSize="@dimen/text_size_normal" /> + app:topLabelText="@string/prime_date_picker_from" + app:topLabelTextColor="@color/white" + app:topLabelTextSize="@dimen/text_size_small" /> + app:topLabelText="@string/prime_date_picker_to" + app:topLabelTextColor="@color/white" + app:topLabelTextSize="@dimen/text_size_small" /> \ No newline at end of file diff --git a/library/src/main/res/layout/selection_bar_single_day_container.xml b/library/src/main/res/layout/selection_bar_single_day_container.xml index a7399327..505725e4 100644 --- a/library/src/main/res/layout/selection_bar_single_day_container.xml +++ b/library/src/main/res/layout/selection_bar_single_day_container.xml @@ -10,9 +10,9 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" - android:paddingStart="@dimen/material_size_8" + android:paddingLeft="@dimen/material_size_8" android:paddingTop="@dimen/material_size_4" - android:paddingEnd="@dimen/material_size_8" + android:paddingRight="@dimen/material_size_8" android:paddingBottom="@dimen/material_size_4" app:topLabelText="@string/prime_date_picker_selected_day" app:topLabelTextColor="@color/white" diff --git a/library/src/main/res/values-ar/strings.xml b/library/src/main/res/values-ar/strings.xml index 596e4061..c917b61d 100644 --- a/library/src/main/res/values-ar/strings.xml +++ b/library/src/main/res/values-ar/strings.xml @@ -2,11 +2,11 @@ الیوم إلغاء - انتخاب + اختيار اليوم المحدد من إلى لم يتم تحديد نطاق! لم يتم تحديد يوم! - \ No newline at end of file + diff --git a/java-sample-app/.gitignore b/sample-app-java/.gitignore similarity index 100% rename from java-sample-app/.gitignore rename to sample-app-java/.gitignore diff --git a/sample-app-java/build.gradle b/sample-app-java/build.gradle new file mode 100644 index 00000000..a70b617f --- /dev/null +++ b/sample-app-java/build.gradle @@ -0,0 +1,22 @@ +plugins { + id 'com.android.application' +} + +apply from: rootProject.file('scripts/android.gradle') + +android { + defaultConfig { + applicationId "com.aminography.primedatepicker.sample_java" + vectorDrawables.useSupportLibrary = true + } +} + +dependencies { + implementation project(':library') + + implementation dep.primecalendar + implementation dep.bundles.ui + + testImplementation dep.junit.core + androidTestImplementation dep.bundles.androidTest +} diff --git a/java-sample-app/proguard-rules.pro b/sample-app-java/proguard-rules.pro similarity index 100% rename from java-sample-app/proguard-rules.pro rename to sample-app-java/proguard-rules.pro diff --git a/java-sample-app/src/androidTest/java/com/aminography/primedatepicker/sample/ExampleInstrumentedTest.java b/sample-app-java/src/androidTest/java/com/aminography/primedatepicker/sample/ExampleInstrumentedTest.java similarity index 100% rename from java-sample-app/src/androidTest/java/com/aminography/primedatepicker/sample/ExampleInstrumentedTest.java rename to sample-app-java/src/androidTest/java/com/aminography/primedatepicker/sample/ExampleInstrumentedTest.java diff --git a/java-sample-app/src/main/AndroidManifest.xml b/sample-app-java/src/main/AndroidManifest.xml similarity index 88% rename from java-sample-app/src/main/AndroidManifest.xml rename to sample-app-java/src/main/AndroidManifest.xml index 68a47192..b189c977 100644 --- a/java-sample-app/src/main/AndroidManifest.xml +++ b/sample-app-java/src/main/AndroidManifest.xml @@ -13,7 +13,9 @@ android:theme="@style/AppTheme" tools:ignore="GoogleAppIndexingWarning"> - + @@ -25,4 +27,4 @@ - \ No newline at end of file + diff --git a/java-sample-app/src/main/assets/fonts/Amiri-Regular.ttf b/sample-app-java/src/main/assets/fonts/Amiri-Regular.ttf similarity index 100% rename from java-sample-app/src/main/assets/fonts/Amiri-Regular.ttf rename to sample-app-java/src/main/assets/fonts/Amiri-Regular.ttf diff --git a/java-sample-app/src/main/assets/fonts/IRANSans.ttf b/sample-app-java/src/main/assets/fonts/IRANSans.ttf similarity index 100% rename from java-sample-app/src/main/assets/fonts/IRANSans.ttf rename to sample-app-java/src/main/assets/fonts/IRANSans.ttf diff --git a/java-sample-app/src/main/assets/fonts/Roboto-Regular.ttf b/sample-app-java/src/main/assets/fonts/Roboto-Regular.ttf similarity index 100% rename from java-sample-app/src/main/assets/fonts/Roboto-Regular.ttf rename to sample-app-java/src/main/assets/fonts/Roboto-Regular.ttf diff --git a/java-sample-app/src/main/java/com/aminography/primedatepicker/sample/MyApplication.java b/sample-app-java/src/main/java/com/aminography/primedatepicker/sample/MyApplication.java similarity index 100% rename from java-sample-app/src/main/java/com/aminography/primedatepicker/sample/MyApplication.java rename to sample-app-java/src/main/java/com/aminography/primedatepicker/sample/MyApplication.java diff --git a/java-sample-app/src/main/java/com/aminography/primedatepicker/sample/view/DatePickerActivity.java b/sample-app-java/src/main/java/com/aminography/primedatepicker/sample/view/DatePickerActivity.java similarity index 95% rename from java-sample-app/src/main/java/com/aminography/primedatepicker/sample/view/DatePickerActivity.java rename to sample-app-java/src/main/java/com/aminography/primedatepicker/sample/view/DatePickerActivity.java index 359df875..bbb91cbb 100644 --- a/java-sample-app/src/main/java/com/aminography/primedatepicker/sample/view/DatePickerActivity.java +++ b/sample-app-java/src/main/java/com/aminography/primedatepicker/sample/view/DatePickerActivity.java @@ -1,5 +1,6 @@ package com.aminography.primedatepicker.sample.view; +import android.content.DialogInterface; import android.os.Bundle; import android.text.TextUtils; import android.view.View; @@ -161,6 +162,13 @@ public void onClick(View v) { } datePicker.show(getSupportFragmentManager(), PICKER_TAG); + + datePicker.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialogInterface) { + datePicker = null; + } + }); } }); } @@ -196,21 +204,21 @@ protected void onResume() { } } - private SingleDayPickCallback singleDayPickCallback = new SingleDayPickCallback() { + private final SingleDayPickCallback singleDayPickCallback = new SingleDayPickCallback() { @Override public void onSingleDayPicked(PrimeCalendar singleDay) { longToast(singleDay.getLongDateString()); } }; - private RangeDaysPickCallback rangeDaysPickCallback = new RangeDaysPickCallback() { + private final RangeDaysPickCallback rangeDaysPickCallback = new RangeDaysPickCallback() { @Override public void onRangeDaysPicked(PrimeCalendar startDay, PrimeCalendar endDay) { longToast(String.format("From: %s\nTo: %s", startDay.getLongDateString(), endDay.getLongDateString())); } }; - private MultipleDaysPickCallback multipleDaysPickCallback = new MultipleDaysPickCallback() { + private final MultipleDaysPickCallback multipleDaysPickCallback = new MultipleDaysPickCallback() { @Override public void onMultipleDaysPicked(List multipleDays) { List list = new ArrayList<>(); diff --git a/java-sample-app/src/main/java/com/aminography/primedatepicker/sample/view/MainActivity.java b/sample-app-java/src/main/java/com/aminography/primedatepicker/sample/view/MainActivity.java similarity index 100% rename from java-sample-app/src/main/java/com/aminography/primedatepicker/sample/view/MainActivity.java rename to sample-app-java/src/main/java/com/aminography/primedatepicker/sample/view/MainActivity.java diff --git a/java-sample-app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/sample-app-java/src/main/res/drawable-v24/ic_launcher_foreground.xml similarity index 100% rename from java-sample-app/src/main/res/drawable-v24/ic_launcher_foreground.xml rename to sample-app-java/src/main/res/drawable-v24/ic_launcher_foreground.xml diff --git a/java-sample-app/src/main/res/drawable/ic_launcher_background.xml b/sample-app-java/src/main/res/drawable/ic_launcher_background.xml similarity index 100% rename from java-sample-app/src/main/res/drawable/ic_launcher_background.xml rename to sample-app-java/src/main/res/drawable/ic_launcher_background.xml diff --git a/java-sample-app/src/main/res/layout/activity_date_picker.xml b/sample-app-java/src/main/res/layout/activity_date_picker.xml similarity index 100% rename from java-sample-app/src/main/res/layout/activity_date_picker.xml rename to sample-app-java/src/main/res/layout/activity_date_picker.xml diff --git a/java-sample-app/src/main/res/layout/activity_main.xml b/sample-app-java/src/main/res/layout/activity_main.xml similarity index 100% rename from java-sample-app/src/main/res/layout/activity_main.xml rename to sample-app-java/src/main/res/layout/activity_main.xml diff --git a/java-sample-app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/sample-app-java/src/main/res/mipmap-anydpi-v26/ic_launcher.xml similarity index 100% rename from java-sample-app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml rename to sample-app-java/src/main/res/mipmap-anydpi-v26/ic_launcher.xml diff --git a/java-sample-app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/sample-app-java/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml similarity index 100% rename from java-sample-app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml rename to sample-app-java/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml diff --git a/java-sample-app/src/main/res/mipmap-hdpi/ic_launcher.png b/sample-app-java/src/main/res/mipmap-hdpi/ic_launcher.png similarity index 100% rename from java-sample-app/src/main/res/mipmap-hdpi/ic_launcher.png rename to sample-app-java/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/java-sample-app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/sample-app-java/src/main/res/mipmap-hdpi/ic_launcher_round.png similarity index 100% rename from java-sample-app/src/main/res/mipmap-hdpi/ic_launcher_round.png rename to sample-app-java/src/main/res/mipmap-hdpi/ic_launcher_round.png diff --git a/java-sample-app/src/main/res/mipmap-mdpi/ic_launcher.png b/sample-app-java/src/main/res/mipmap-mdpi/ic_launcher.png similarity index 100% rename from java-sample-app/src/main/res/mipmap-mdpi/ic_launcher.png rename to sample-app-java/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/java-sample-app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/sample-app-java/src/main/res/mipmap-mdpi/ic_launcher_round.png similarity index 100% rename from java-sample-app/src/main/res/mipmap-mdpi/ic_launcher_round.png rename to sample-app-java/src/main/res/mipmap-mdpi/ic_launcher_round.png diff --git a/java-sample-app/src/main/res/mipmap-xhdpi/ic_launcher.png b/sample-app-java/src/main/res/mipmap-xhdpi/ic_launcher.png similarity index 100% rename from java-sample-app/src/main/res/mipmap-xhdpi/ic_launcher.png rename to sample-app-java/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/java-sample-app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/sample-app-java/src/main/res/mipmap-xhdpi/ic_launcher_round.png similarity index 100% rename from java-sample-app/src/main/res/mipmap-xhdpi/ic_launcher_round.png rename to sample-app-java/src/main/res/mipmap-xhdpi/ic_launcher_round.png diff --git a/java-sample-app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/sample-app-java/src/main/res/mipmap-xxhdpi/ic_launcher.png similarity index 100% rename from java-sample-app/src/main/res/mipmap-xxhdpi/ic_launcher.png rename to sample-app-java/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/java-sample-app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/sample-app-java/src/main/res/mipmap-xxhdpi/ic_launcher_round.png similarity index 100% rename from java-sample-app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png rename to sample-app-java/src/main/res/mipmap-xxhdpi/ic_launcher_round.png diff --git a/java-sample-app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/sample-app-java/src/main/res/mipmap-xxxhdpi/ic_launcher.png similarity index 100% rename from java-sample-app/src/main/res/mipmap-xxxhdpi/ic_launcher.png rename to sample-app-java/src/main/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/java-sample-app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/sample-app-java/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png similarity index 100% rename from java-sample-app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png rename to sample-app-java/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png diff --git a/java-sample-app/src/main/res/values/colors.xml b/sample-app-java/src/main/res/values/colors.xml similarity index 100% rename from java-sample-app/src/main/res/values/colors.xml rename to sample-app-java/src/main/res/values/colors.xml diff --git a/java-sample-app/src/main/res/values/dimens.xml b/sample-app-java/src/main/res/values/dimens.xml similarity index 100% rename from java-sample-app/src/main/res/values/dimens.xml rename to sample-app-java/src/main/res/values/dimens.xml diff --git a/java-sample-app/src/main/res/values/strings.xml b/sample-app-java/src/main/res/values/strings.xml similarity index 100% rename from java-sample-app/src/main/res/values/strings.xml rename to sample-app-java/src/main/res/values/strings.xml diff --git a/java-sample-app/src/main/res/values/styles.xml b/sample-app-java/src/main/res/values/styles.xml similarity index 100% rename from java-sample-app/src/main/res/values/styles.xml rename to sample-app-java/src/main/res/values/styles.xml diff --git a/java-sample-app/src/test/java/com/aminography/primedatepicker/sample/ExampleUnitTest.java b/sample-app-java/src/test/java/com/aminography/primedatepicker/sample/ExampleUnitTest.java similarity index 100% rename from java-sample-app/src/test/java/com/aminography/primedatepicker/sample/ExampleUnitTest.java rename to sample-app-java/src/test/java/com/aminography/primedatepicker/sample/ExampleUnitTest.java diff --git a/sample-app/build.gradle b/sample-app/build.gradle index 4a71c946..e0295be2 100644 --- a/sample-app/build.gradle +++ b/sample-app/build.gradle @@ -1,50 +1,25 @@ -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' +plugins { + id 'com.android.application' + id 'kotlin-android' + id 'kotlin-android-extensions' +} -android { - compileSdkVersion 29 +apply from: rootProject.file('scripts/android.gradle') +apply from: rootProject.file('scripts/kotlin.gradle') +android { defaultConfig { - applicationId "com.aminography.primedatepicker.sampleapp" - minSdkVersion 14 - targetSdkVersion 29 - - versionCode 320 - versionName "3.2.0" - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + applicationId "com.aminography.primedatepicker.sample" vectorDrawables.useSupportLibrary = true } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } -} - -repositories { - jcenter() } dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation "com.google.android.material:material:$material_version" - implementation "androidx.appcompat:appcompat:$appcompat_version" - - // ------- Kotlin - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - - // ------- PrimeDatePicker implementation project(':library') - // ------- PrimeCalendar - implementation "com.aminography:primecalendar:$primecalendar_version" + implementation dep.primecalendar + implementation dep.bundles.ui - // ------- Test - testImplementation "junit:junit:$junit_version" - androidTestImplementation "androidx.test.ext:junit:$androidx_junit_version" - androidTestImplementation "androidx.test.espresso:espresso-core:$androidx_espresso_version" + testImplementation dep.junit.core + androidTestImplementation dep.bundles.androidTest } diff --git a/sample-app/src/main/AndroidManifest.xml b/sample-app/src/main/AndroidManifest.xml index 607b0836..9bf50973 100644 --- a/sample-app/src/main/AndroidManifest.xml +++ b/sample-app/src/main/AndroidManifest.xml @@ -13,7 +13,9 @@ android:theme="@style/AppTheme" tools:ignore="GoogleAppIndexingWarning"> - + @@ -37,4 +39,4 @@ - \ No newline at end of file + diff --git a/sample-app/src/main/assets/fonts/Righteous-Regular.ttf b/sample-app/src/main/assets/fonts/Righteous-Regular.ttf new file mode 100644 index 00000000..fc9c0a84 Binary files /dev/null and b/sample-app/src/main/assets/fonts/Righteous-Regular.ttf differ diff --git a/sample-app/src/main/java/com/aminography/primedatepicker/sample/view/DatePickerActivity.kt b/sample-app/src/main/java/com/aminography/primedatepicker/sample/view/DatePickerActivity.kt index ec7e20a7..965914d8 100644 --- a/sample-app/src/main/java/com/aminography/primedatepicker/sample/view/DatePickerActivity.kt +++ b/sample-app/src/main/java/com/aminography/primedatepicker/sample/view/DatePickerActivity.kt @@ -66,6 +66,8 @@ class DatePickerActivity : AppCompatActivity() { } datePicker?.show(supportFragmentManager, PICKER_TAG) + + datePicker?.setOnDismissListener { datePicker = null } } } @@ -77,17 +79,19 @@ class DatePickerActivity : AppCompatActivity() { override fun onResume() { super.onResume() datePicker = supportFragmentManager.findFragmentByTag(PICKER_TAG) as? PrimeDatePicker - when (datePicker?.pickType) { - PickType.SINGLE -> { - datePicker?.setDayPickCallback(singleDayPickCallback) - } - PickType.RANGE_START, PickType.RANGE_END -> { - datePicker?.setDayPickCallback(rangeDaysPickCallback) - } - PickType.MULTIPLE -> { - datePicker?.setDayPickCallback(multipleDaysPickCallback) - } - else -> { + datePicker?.let { + when (it.pickType) { + PickType.SINGLE -> { + it.setDayPickCallback(singleDayPickCallback) + } + PickType.RANGE_START, PickType.RANGE_END -> { + it.setDayPickCallback(rangeDaysPickCallback) + } + PickType.MULTIPLE -> { + it.setDayPickCallback(multipleDaysPickCallback) + } + else -> { + } } } } @@ -133,14 +137,14 @@ class DatePickerActivity : AppCompatActivity() { private fun getDefaultTheme(typeface: String): ThemeFactory { return when { lightThemeRadioButton.isChecked -> object : LightThemeFactory() { - override val typefacePath: String? + override val typefacePath: String get() = typeface // override val pickedDayBackgroundShapeType: BackgroundShapeType // get() = BackgroundShapeType.ROUND_SQUARE } else -> object : DarkThemeFactory() { - override val typefacePath: String? + override val typefacePath: String get() = typeface // override val calendarViewShowAdjacentMonthDays: Boolean diff --git a/scripts/android.gradle b/scripts/android.gradle new file mode 100644 index 00000000..a83f8b67 --- /dev/null +++ b/scripts/android.gradle @@ -0,0 +1,25 @@ +android { + compileSdk versions.compileSdk + + defaultConfig { + minSdk versions.minSdk + targetSdk versions.targetSdk + + versionCode libVersion.code + versionName libVersion.name + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility versions.javaTarget + targetCompatibility versions.javaTarget + } +} diff --git a/scripts/kotlin.gradle b/scripts/kotlin.gradle new file mode 100644 index 00000000..e3db7d00 --- /dev/null +++ b/scripts/kotlin.gradle @@ -0,0 +1,5 @@ +android { + kotlinOptions { + jvmTarget = versions.kotlinJvmTarget + } +} diff --git a/scripts/publish-module.gradle b/scripts/publish-module.gradle new file mode 100644 index 00000000..a5093000 --- /dev/null +++ b/scripts/publish-module.gradle @@ -0,0 +1,91 @@ +apply plugin: 'maven-publish' +apply plugin: 'signing' +apply plugin: 'org.jetbrains.dokka' + +task androidSourcesJar(type: Jar) { + archiveClassifier.set('sources') + if (project.plugins.findPlugin("com.android.library")) { + from android.sourceSets.main.java.srcDirs + from android.sourceSets.main.kotlin.srcDirs + } else { + from sourceSets.main.java.srcDirs + from sourceSets.main.kotlin.srcDirs + } +} + +tasks.withType(dokkaHtmlPartial.getClass()).configureEach { + pluginsMapConfiguration.set( + ["org.jetbrains.dokka.base.DokkaBase": """{ "separateInheritedMembers": true}"""] + ) +} + +task javadocJar(type: Jar, dependsOn: dokkaJavadoc) { + archiveClassifier.set('javadoc') + from dokkaJavadoc.outputDirectory +} + +artifacts { + archives androidSourcesJar + archives javadocJar +} + +group = publishInfo.groupId +version = publishInfo.version + +afterEvaluate { + publishing { + publications { + release(MavenPublication) { + + groupId publishInfo.groupId + artifactId publishInfo.artifactId + version publishInfo.version + + if (project.plugins.findPlugin("com.android.library")) { + from components.release + } else { + from components.java + } + + artifact androidSourcesJar + artifact javadocJar + + pom { + name = publishInfo.artifactId + description = publishInfo.description + url = "https://github.com/aminography/${publishInfo.githubRepo}" + + licenses { + license { + name = 'License' + url = "https://github.com/aminography/${publishInfo.githubRepo}/blob/main/LICENSE.md" + } + } + + developers { + developer { + id = 'aminography' + name = 'Amin Hassani' + email = 'aminography@gmail.com' + } + } + + scm { + connection = "scm:git:github.com/aminography/${publishInfo.githubRepo}.git" + developerConnection = "scm:git:ssh://github.com/aminography/${publishInfo.githubRepo}.git" + url = "https://github.com/aminography/${publishInfo.githubRepo}/tree/main" + } + } + } + } + } +} + +signing { + useInMemoryPgpKeys( + rootProject.ext["signing.keyId"], + rootProject.ext["signing.key"], + rootProject.ext["signing.password"], + ) + sign publishing.publications +} diff --git a/scripts/publish-root.gradle b/scripts/publish-root.gradle new file mode 100644 index 00000000..5f603b93 --- /dev/null +++ b/scripts/publish-root.gradle @@ -0,0 +1,37 @@ +// Create variables with empty default values +ext["ossrhUsername"] = '' +ext["ossrhPassword"] = '' +ext["sonatypeStagingProfileId"] = '' +ext["signing.keyId"] = '' +ext["signing.password"] = '' +ext["signing.key"] = '' + +File secretPropsFile = project.rootProject.file('local.properties') +if (secretPropsFile.exists()) { + // Read local.properties file first if it exists + Properties p = new Properties() + new FileInputStream(secretPropsFile).withCloseable { is -> p.load(is) } + p.each { name, value -> ext[name] = value } +} else { + // Use system environment variables + ext["ossrhUsername"] = System.getenv('OSSRH_USERNAME') + ext["ossrhPassword"] = System.getenv('OSSRH_PASSWORD') + ext["sonatypeStagingProfileId"] = System.getenv('SONATYPE_STAGING_PROFILE_ID') + ext["signing.keyId"] = System.getenv('SIGNING_KEY_ID') + ext["signing.password"] = System.getenv('SIGNING_PASSWORD') + ext["signing.key"] = System.getenv('SIGNING_KEY') +} + +// Set up Sonatype repository +nexusPublishing { + repositories { + sonatype { + stagingProfileId = sonatypeStagingProfileId + username = ossrhUsername + password = ossrhPassword + version = libVersion.name + nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) + snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) + } + } +} diff --git a/scripts/versions.gradle b/scripts/versions.gradle new file mode 100644 index 00000000..c6abb2e1 --- /dev/null +++ b/scripts/versions.gradle @@ -0,0 +1,19 @@ +// semantic versioning +def semantic = [ + 'major': 3, + 'minor': 6, + 'patch': 1, +] +ext.libVersion = [ + 'code': semantic.major * 1000000 + semantic.minor * 1000 + semantic.patch, + 'name': "${semantic.major}.${semantic.minor}.${semantic.patch}", +] + +// configuration versions +ext.versions = [ + 'javaTarget' : JavaVersion.VERSION_1_8, + 'kotlinJvmTarget': '1.8', + 'compileSdk' : 31, + 'targetSdk' : 31, + 'minSdk' : 14, +] diff --git a/settings.gradle b/settings.gradle index d1806efb..f306a332 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,44 @@ -include ':sample-app', ':library', ':java-sample-app' \ No newline at end of file +rootProject.name = "PrimeDatePicker" +include ':library' +include ':sample-app' +include ':sample-app-java' + +enableFeaturePreview('VERSION_CATALOGS') +dependencyResolutionManagement { + versionCatalogs { + dep { + alias('primecalendar').to('com.aminography:primecalendar:1.7.0') + alias('androidx-lifecycleKtx').to('androidx.lifecycle:lifecycle-runtime-ktx:2.2.0') + + version('coroutines', '1.5.2') + alias('coroutines-core').to('org.jetbrains.kotlinx', 'kotlinx-coroutines-core').versionRef('coroutines') + alias('coroutines-android').to('org.jetbrains.kotlinx', 'kotlinx-coroutines-android').versionRef('coroutines') + bundle('coroutines', ['coroutines-core', 'coroutines-android']) + + alias('androidx-appcompat').to('androidx.appcompat:appcompat:1.2.0') + alias('androidx-constraintlayout').to('androidx.constraintlayout:constraintlayout:2.0.4') + alias('android-material').to('com.google.android.material:material:1.2.1') + bundle('ui', ['androidx-appcompat', 'androidx-constraintlayout', 'android-material']) + + alias('junit-core').to('junit:junit:4.13.2') + alias('androidx-junit').to('androidx.test.ext:junit:1.1.3') + alias('androidx-espresso').to('androidx.test.espresso:espresso-core:3.4.0') + bundle('androidTest', ['androidx-junit', 'androidx-espresso']) + } + + plugin { + alias('android-gradle').to('com.android.tools.build:gradle:7.0.4') + alias('jetbrains-kotlin').to('org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10') + alias('jetbrains-dokka').to('org.jetbrains.dokka:dokka-gradle-plugin:1.5.0') + alias('nexus-publish').to('io.github.gradle-nexus:publish-plugin:1.1.0') + } + } +} + +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} diff --git a/static/theme_light.png b/static/theme_light.png new file mode 100644 index 00000000..92d32a07 Binary files /dev/null and b/static/theme_light.png differ diff --git a/static/theme_light_customized.png b/static/theme_light_customized.png new file mode 100644 index 00000000..81c4b8ea Binary files /dev/null and b/static/theme_light_customized.png differ