├── .DS_Store
├── .github
└── FUNDING.yml
├── .gitignore
├── .idea
├── .name
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── compiler.xml
├── jarRepositories.xml
└── misc.xml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── tejpratapsingh
│ │ └── recyclercalendaractivity
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── ic_launcher-web.png
│ ├── java
│ │ └── com
│ │ │ └── tejpratapsingh
│ │ │ └── recyclercalendaractivity
│ │ │ ├── MainActivity.kt
│ │ │ ├── horizontal
│ │ │ ├── HorizontalCalendarActivity.kt
│ │ │ └── HorizontalRecyclerCalendarAdapter.kt
│ │ │ ├── model
│ │ │ └── SimpleEvent.kt
│ │ │ ├── simple
│ │ │ ├── InfiniteRecyclerCalendarActivity.kt
│ │ │ └── SimpleRecyclerCalendarActivity.kt
│ │ │ ├── vertical
│ │ │ ├── VerticalCalendarActivity.kt
│ │ │ └── VerticalRecyclerCalendarAdapter.kt
│ │ │ └── viewpager
│ │ │ ├── ViewPagerCalendarActivity.kt
│ │ │ ├── ViewPagerRecyclerCalendarAdapter.kt
│ │ │ └── ui
│ │ │ └── main
│ │ │ ├── PlaceholderFragment.kt
│ │ │ └── SectionsPagerAdapter.kt
│ └── res
│ │ ├── drawable-anydpi
│ │ └── ic_action_setting.xml
│ │ ├── drawable-hdpi
│ │ └── ic_action_setting.png
│ │ ├── drawable-mdpi
│ │ └── ic_action_setting.png
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable-xhdpi
│ │ └── ic_action_setting.png
│ │ ├── drawable-xxhdpi
│ │ └── ic_action_setting.png
│ │ ├── drawable
│ │ ├── circle_shape.xml
│ │ ├── circular_progress_bar.xml
│ │ ├── ic_calendar.png
│ │ ├── ic_launcher_background.xml
│ │ ├── ic_launcher_foreground.xml
│ │ ├── layout_round_corner.xml
│ │ └── layout_round_corner_filled.xml
│ │ ├── layout
│ │ ├── activity_horizontal_calendar.xml
│ │ ├── activity_infinite_recycler_calendar.xml
│ │ ├── activity_main.xml
│ │ ├── activity_simple_recycler_calendar.xml
│ │ ├── activity_vertical_calendar.xml
│ │ ├── activity_view_pager_calendar.xml
│ │ ├── fragment_view_pager_calendar.xml
│ │ ├── item_calendar_horizontal.xml
│ │ ├── item_calendar_vertical.xml
│ │ └── item_calendar_view_pager.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── tejpratapsingh
│ └── recyclercalendaractivity
│ └── ExampleUnitTest.kt
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── jitpack.yml
├── recyclercalendar
├── .gitignore
├── build.gradle
├── consumer-rules.pro
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── tejpratapsingh
│ │ └── recyclercalendar
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── tejpratapsingh
│ │ │ └── recyclercalendar
│ │ │ ├── adapter
│ │ │ ├── InfiniteRecyclerCalenderAdapter.kt
│ │ │ ├── RecyclerCalendarBaseAdapter.kt
│ │ │ └── SimpleRecyclerCalendarAdapter.kt
│ │ │ ├── model
│ │ │ ├── InfiniteRecyclerCalendarConfiguration.kt
│ │ │ ├── RecyclerCalendarConfiguration.kt
│ │ │ ├── RecyclerCalenderViewItem.kt
│ │ │ └── SimpleRecyclerCalendarConfiguration.kt
│ │ │ ├── utilities
│ │ │ └── CalendarUtils.kt
│ │ │ └── views
│ │ │ ├── InfiniteRecyclerCalendarView.kt
│ │ │ └── SimpleRecyclerCalendarView.kt
│ └── res
│ │ ├── drawable-v21
│ │ ├── layout_round_corner_filled.xml
│ │ ├── layout_round_corner_left_filled.xml
│ │ ├── layout_round_corner_middle_filled.xml
│ │ └── layout_round_corner_right_filled.xml
│ │ ├── drawable
│ │ ├── layout_round_corner_filled.xml
│ │ ├── layout_round_corner_left_filled.xml
│ │ ├── layout_round_corner_middle_filled.xml
│ │ └── layout_round_corner_right_filled.xml
│ │ ├── layout
│ │ ├── item_infinite_calendar.xml
│ │ └── item_simple_calendar.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ └── strings.xml
│ └── test
│ └── java
│ └── com
│ └── tejpratapsingh
│ └── recyclercalendar
│ └── ExampleUnitTest.kt
├── sample_images
├── .DS_Store
├── backdrop.png
├── cover.png
├── month_vertical.gif
├── month_vertical.mp4
├── progress_sample.gif
├── progress_sample.mp4
├── simplecalendar.jpeg
├── simplecalendar_framed.png
├── week_example.gif
└── week_example.mp4
└── settings.gradle
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/.DS_Store
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: tejpratap
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: ['https://www.paypal.com/paypalme2/tejpratap46/3']
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.aar
4 | *.ap_
5 | *.aab
6 |
7 | # Files for the ART/Dalvik VM
8 | *.dex
9 |
10 | # Java class files
11 | *.class
12 |
13 | # Generated files
14 | bin/
15 | gen/
16 | out/
17 | # Uncomment the following line in case you need and you don't have the release build type files in your app
18 | # release/
19 |
20 | # Gradle files
21 | .gradle/
22 | build/
23 |
24 | # Local configuration file (sdk path, etc)
25 | local.properties
26 |
27 | # Proguard folder generated by Eclipse
28 | proguard/
29 |
30 | # Log Files
31 | *.log
32 |
33 | # Android Studio Navigation editor temp files
34 | .navigation/
35 |
36 | # Android Studio captures folder
37 | captures/
38 |
39 | # IntelliJ
40 | *.iml
41 | .idea/workspace.xml
42 | .idea/tasks.xml
43 | .idea/gradle.xml
44 | .idea/assetWizardSettings.xml
45 | .idea/dictionaries
46 | .idea/libraries
47 | # Android Studio 3 in .gitignore file.
48 | .idea/caches
49 | .idea/modules.xml
50 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you
51 | .idea/navEditor.xml
52 |
53 | # Keystore files
54 | # Uncomment the following lines if you do not want to check your keystore files in.
55 | #*.jks
56 | #*.keystore
57 |
58 | # External native build folder generated in Android Studio 2.2 and later
59 | .externalNativeBuild
60 | .cxx/
61 |
62 | # Google Services (e.g. APIs or Firebase)
63 | # google-services.json
64 |
65 | # Freeline
66 | freeline.py
67 | freeline/
68 | freeline_project_description.json
69 |
70 | # fastlane
71 | fastlane/report.xml
72 | fastlane/Preview.html
73 | fastlane/screenshots
74 | fastlane/test_output
75 | fastlane/readme.md
76 |
77 | # Version control
78 | vcs.xml
79 |
80 | # lint
81 | lint/intermediates/
82 | lint/generated/
83 | lint/outputs/
84 | lint/tmp/
85 | # lint/reports/
86 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | RecyclerCalendarActivity
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | xmlns:android
17 |
18 | ^$
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | xmlns:.*
28 |
29 | ^$
30 |
31 |
32 | BY_NAME
33 |
34 |
35 |
36 |
37 |
38 |
39 | .*:id
40 |
41 | http://schemas.android.com/apk/res/android
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | .*:name
51 |
52 | http://schemas.android.com/apk/res/android
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | name
62 |
63 | ^$
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | style
73 |
74 | ^$
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | .*
84 |
85 | ^$
86 |
87 |
88 | BY_NAME
89 |
90 |
91 |
92 |
93 |
94 |
95 | .*
96 |
97 | http://schemas.android.com/apk/res/android
98 |
99 |
100 | ANDROID_ATTRIBUTE_ORDER
101 |
102 |
103 |
104 |
105 |
106 |
107 | .*
108 |
109 | .*
110 |
111 |
112 | BY_NAME
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Tej Pratap Sngh
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # RecyclerCalendarAndroid
4 |
5 | [](https://jitpack.io/#tejpratap46/RecyclerCalendarAndroid)
6 |
7 | A DIY calendar generator library for android written in Kotlin.
8 |
9 | Step 1. Add the JitPack repository to your build file
10 | Add it in your root build.gradle at the end of repositories:
11 | ```gradle
12 | allprojects {
13 | repositories {
14 | ...
15 | maven {
16 | url 'https://jitpack.io'
17 | }
18 | }
19 | }
20 | ```
21 |
22 | Step 2. Add the dependency
23 | ```gradle
24 | dependencies {
25 | implementation 'com.github.tejpratap46:RecyclerCalendarAndroid:LATEST_RELEASE_TAG'
26 | }
27 | ```
28 | ## Try It
29 | [](https://play.google.com/store/apps/details?id=com.tejpratapsingh.recyclercalendaractivity)
30 |
31 | ### Here are sample calenders you can create with this library :
32 |
33 | | Week Calendar | Month With Events | Month With Swipe Pages |
34 | | -- | -- | -- |
35 | | Code At: [horizontal](https://github.com/tejpratap46/RecyclerCalendarAndroid/tree/master/app/src/main/java/com/tejpratapsingh/recyclercalendaractivity/horizontal) | Code At: [vertical](https://github.com/tejpratap46/RecyclerCalendarAndroid/tree/master/app/src/main/java/com/tejpratapsingh/recyclercalendaractivity/vertical) | Code At: [viewpager](https://github.com/tejpratap46/RecyclerCalendarAndroid/tree/master/app/src/main/java/com/tejpratapsingh/recyclercalendaractivity/viewpager)
36 | |  |  |  |
37 |
38 | **Above sample are not the limit of this library, possiblities are endless as you can create custom view for each date as well as add custom Business Login on top of it.**
39 |
40 | ------------
41 |
42 | Here is how you can create your own Calendar using **RecyclerCalendarAndroid**.
43 | Create a RecyclerView Adapter which extends `RecyclerCalendarBaseAdapter`
44 |
45 | 1. Implement following methods:
46 | ```kotlin
47 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
48 | val view: View = LayoutInflater.from(parent.context).inflate(R.layout.item_calendar_horizontal, parent, false)
49 | return MonthCalendarViewHolder(view)
50 | }
51 | ```
52 |
53 | 2. Create `ViewHolder` Class for you `View` which extends `RecyclerView.ViewHolder`:
54 | ```kotlin
55 | class MonthCalendarViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
56 | val textViewDay: TextView = itemView.findViewById(R.id.textCalenderItemVerticalDay)
57 | val textViewDate: TextView = itemView.findViewById(R.id.textCalenderItemVerticalDate)
58 | val viewEvent: View = itemView.findViewById(R.id.viewCalenderItemVerticalEvent)
59 | }
60 | ```
61 |
62 | 3. Now just implament `onBindViewHolder`
63 | ```kotlin
64 | override fun onBindViewHolder(
65 | holder: RecyclerView.ViewHolder,
66 | position: Int,
67 | calendarItem: RecyclerCalenderViewItem
68 | ) {
69 | val monthViewHolder: MonthCalendarViewHolder = holder as MonthCalendarViewHolder
70 | // first reset view of current item as it will be reused for different dates and header.
71 | {
72 | // Reset all you view here...
73 | monthViewHolder.itemView.visibility = View.VISIBLE
74 | monthViewHolder.itemView.setOnClickListener(null)
75 | }
76 |
77 | // Calendar item as 3 parts
78 | // 1. Header -> Where you put month name, year etc.
79 | // 2. Empty Space -> This is empty space to fill days before first day of month start, hide every view of ViewHolder Here
80 | // 3. Date -> This is a date, customise your date with event, tecket information, Available slot OR just selection etc here
81 | if (calendarItem.isHeader) {
82 | val selectedCalendar = Calendar.getInstance(Locale.getDefault())
83 | selectedCalendar.time = calendarItem.date
84 |
85 | val month: String = CalendarUtils.getMonth(selectedCalendar.get(Calendar.MONTH)) ?: ""
86 | val year = selectedCalendar[Calendar.YEAR].toLong()
87 |
88 | monthViewHolder.textViewDay.text = year.toString()
89 | monthViewHolder.textViewDate.text = month
90 | } else if (calendarItem.isEmpty) {
91 | monthViewHolder.itemView.visibility = View.GONE
92 | monthViewHolder.textViewDay.text = ""
93 | monthViewHolder.textViewDate.text = ""
94 | } else {
95 | val calendarDate = Calendar.getInstance(Locale.getDefault())
96 | calendarDate.time = calendarItem.date
97 |
98 | val day: String = CalendarUtils.getDay(calendarDate.get(Calendar.DAY_OF_WEEK)) ?: ""
99 |
100 | monthViewHolder.textViewDay.text = day
101 |
102 | val dateInt: Int =
103 | (CalendarUtils.dateStringFromFormat(calendarDate.time, CalendarUtils.DB_DATE_FORMAT)
104 | ?: "0").toInt()
105 |
106 | if (eventMap.contains(dateInt)) {
107 | // As an example, here im checking if this date has any event passed from constructor
108 | monthViewHolder.viewEvent.visibility = View.VISIBLE
109 | // Set background color from event information
110 | monthViewHolder.viewEvent.setBackgroundColor(eventMap.get(dateInt)!!.color)
111 | }
112 |
113 | // Set Date to textView
114 | monthViewHolder.textViewDate.text = CalendarUtils.dateStringFromFormat(calendarDate.time, CalendarUtils.DISPLAY_DATE_FORMAT) ?: ""
115 |
116 | // Here as an example, im sending Tap data to listener
117 | monthViewHolder.itemView.setOnClickListener {
118 | dateSelectListener.onDateSelected(calendarItem.date, eventMap[dateInt])
119 | }
120 | }
121 | }
122 | ```
123 | *above code is direct example from [VerticalRecyclerCalendarAdapter](https://github.com/tejpratap46/RecyclerCalendarAndroid/blob/master/app/src/main/java/com/tejpratapsingh/recyclercalendaractivity/vertical/VerticalRecyclerCalendarAdapter.kt)*
124 |
125 | ------------
126 |
127 | #### For People who want to just use simple date picker/selection calendar, i have created `SimpleRecyclerCalendarView`
128 | To use `SimpleRecyclerCalendarView`, just include following in your `.xml`
129 |
130 | ```xml
131 |
135 | ```
136 |
137 | And in Your Activity, include following
138 | ```kotlin
139 | val calenderView: SimpleRecyclerCalendarView = findViewById(R.id.calendarRecyclerView)
140 |
141 | val date = Date()
142 | date.time = System.currentTimeMillis()
143 |
144 | // Start From Date
145 | val startCal = Calendar.getInstance()
146 |
147 | // End Date
148 | val endCal = Calendar.getInstance()
149 | endCal.time = date
150 | endCal.add(Calendar.MONTH, 3)
151 |
152 | val configuration: SimpleRecyclerCalendarConfiguration =
153 | SimpleRecyclerCalendarConfiguration(
154 | calenderViewType = RecyclerCalendarConfiguration.CalenderViewType.VERTICAL, // calendarViewType could be VERTICAL OR HORIZONTAL
155 | calendarLocale = Locale.getDefault(),
156 | includeMonthHeader = true,
157 | selectionMode = SimpleRecyclerCalendarConfiguration.SelectionModeNone() // selectionMode could be one of [SelectionModeNone, SelectionModeSingle, SelectionModeMultiple, SelectionModeRange]
158 | )
159 | configuration.weekStartOffset = RecyclerCalendarConfiguration.START_DAY_OF_WEEK.MONDAY
160 |
161 |
162 | calenderView!!.initialise(
163 | startDate,
164 | endDate,
165 | configuration,
166 | object : SimpleRecyclerCalendarAdapter.OnDateSelected {
167 | override fun onDateSelected(date: Date) {
168 | Toast.makeText(
169 | calenderView!!.context,
170 | "Date Selected: ${CalendarUtils.getGmt(date)}",
171 | Toast.LENGTH_LONG
172 | ).show()
173 | }
174 | })
175 | ```
176 | *To know More about SimpleRecyclerCalendarView visit [SimpleRecyclerCalendarActivity](https://github.com/tejpratap46/RecyclerCalendarAndroid/blob/master/app/src/main/java/com/tejpratapsingh/recyclercalendaractivity/simple/SimpleRecyclerCalendarActivity.kt)*
177 |
178 | #### For People who want to just use infinite date picker/selection calendar, i have created `InfiniteRecyclerCalendarView`
179 | To use `InfiniteRecyclerCalendarView`, just include following in your `.xml`
180 |
181 | ```xml
182 |
186 | ```
187 |
188 | And in Your Activity, include following
189 | ```kotlin
190 | val calenderView: InfiniteRecyclerCalendarView = findViewById(R.id.calendarRecyclerView)
191 |
192 | val date = Date()
193 | date.time = System.currentTimeMillis()
194 |
195 | // Start From Date
196 | val startCal = Calendar.getInstance()
197 |
198 | // End Date
199 | val endCal = Calendar.getInstance()
200 | endCal.time = date
201 | endCal.add(Calendar.MONTH, 3)
202 |
203 | val configuration: InfiniteRecyclerCalendarConfiguration =
204 | InfiniteRecyclerCalendarConfiguration(
205 | calenderViewType = RecyclerCalendarConfiguration.CalenderViewType.VERTICAL, // calendarViewType could be VERTICAL OR HORIZONTAL
206 | calendarLocale = Locale.getDefault(),
207 | includeMonthHeader = true,
208 | selectionMode = InfiniteRecyclerCalendarConfiguration.SelectionModeNone() // selectionMode could be one of [SelectionModeNone, SelectionModeSingle, SelectionModeMultiple, SelectionModeRange]
209 | )
210 | configuration.weekStartOffset = RecyclerCalendarConfiguration.START_DAY_OF_WEEK.MONDAY
211 |
212 | calenderView!!.initialise(
213 | configuration,
214 | object : InfiniteRecyclerCalenderAdapter.OnDateSelected {
215 | override fun onDateSelected(date: Date) {
216 | Toast.makeText(
217 | calenderView!!.context,
218 | "Date Selected: ${CalendarUtils.getGmt(date)}",
219 | Toast.LENGTH_LONG
220 | ).show()
221 | }
222 | })
223 | ```
224 | *To know More about InfiniteRecyclerCalendarActivity visit [InfiniteRecyclerCalendarActivity](https://github.com/tejpratap46/RecyclerCalendarAndroid/blob/master/app/src/main/java/com/tejpratapsingh/recyclercalendaractivity/simple/InfiniteRecyclerCalendarActivity.kt)*
225 |
226 | ## Donate
227 | [](https://ko-fi.com/M4M413CJC)
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android'
3 |
4 | android {
5 | compileSdkVersion 30
6 | defaultConfig {
7 | applicationId "com.tejpratapsingh.recyclercalendaractivity"
8 | minSdkVersion 15
9 | targetSdkVersion 30
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | implementation fileTree(dir: 'libs', include: ['*.jar'])
24 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
25 | implementation 'androidx.appcompat:appcompat:1.3.1'
26 | implementation 'androidx.core:core-ktx:1.6.0'
27 | implementation 'androidx.recyclerview:recyclerview:1.2.1'
28 | implementation project(path: ':recyclercalendar')
29 | implementation 'com.google.android.material:material:1.4.0'
30 | testImplementation 'junit:junit:4.13.2'
31 | androidTestImplementation 'androidx.test.ext:junit:1.1.3'
32 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
33 | }
34 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/tejpratapsingh/recyclercalendaractivity/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendaractivity
2 |
3 | import androidx.test.platform.app.InstrumentationRegistry
4 | import androidx.test.ext.junit.runners.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22 | assertEquals("com.tejpratapsingh.recyclercalendaractivity", appContext.packageName)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
14 |
17 |
20 |
23 |
26 |
29 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/ic_launcher-web.png
--------------------------------------------------------------------------------
/app/src/main/java/com/tejpratapsingh/recyclercalendaractivity/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendaractivity
2 |
3 | import android.content.Intent
4 | import android.os.Bundle
5 | import android.widget.LinearLayout
6 | import androidx.appcompat.app.AppCompatActivity
7 | import com.tejpratapsingh.recyclercalendaractivity.horizontal.HorizontalCalendarActivity
8 | import com.tejpratapsingh.recyclercalendaractivity.simple.InfiniteRecyclerCalendarActivity
9 | import com.tejpratapsingh.recyclercalendaractivity.simple.SimpleRecyclerCalendarActivity
10 | import com.tejpratapsingh.recyclercalendaractivity.vertical.VerticalCalendarActivity
11 | import com.tejpratapsingh.recyclercalendaractivity.viewpager.ViewPagerCalendarActivity
12 |
13 | class MainActivity : AppCompatActivity() {
14 |
15 | override fun onCreate(savedInstanceState: Bundle?) {
16 | super.onCreate(savedInstanceState)
17 | setContentView(R.layout.activity_main)
18 |
19 | val layoutWeekCalendar: LinearLayout = findViewById(R.id.layoutWeekCalendarActivity);
20 | layoutWeekCalendar.setOnClickListener {
21 | val intent: Intent = Intent(this@MainActivity, HorizontalCalendarActivity::class.java)
22 | startActivity(intent)
23 | }
24 |
25 | val layoutMonthCalendar: LinearLayout = findViewById(R.id.layoutMonthCalendarActivity);
26 | layoutMonthCalendar.setOnClickListener {
27 | val intent: Intent = Intent(this@MainActivity, VerticalCalendarActivity::class.java)
28 | startActivity(intent)
29 | }
30 |
31 | val layoutPageCalendar: LinearLayout = findViewById(R.id.layoutPageCalendarActivity);
32 | layoutPageCalendar.setOnClickListener {
33 | val intent: Intent = Intent(this@MainActivity, ViewPagerCalendarActivity::class.java)
34 | startActivity(intent)
35 | }
36 |
37 | val layoutSimpleCalendar: LinearLayout = findViewById(R.id.layoutSimpleCalendarActivity);
38 | layoutSimpleCalendar.setOnClickListener {
39 | val intent: Intent =
40 | Intent(this@MainActivity, SimpleRecyclerCalendarActivity::class.java)
41 | startActivity(intent)
42 | }
43 |
44 | val layoutInfiniteCalendar: LinearLayout =
45 | findViewById(R.id.layoutInfiniteCalendarActivity);
46 | layoutInfiniteCalendar.setOnClickListener {
47 | val intent: Intent =
48 | Intent(this@MainActivity, InfiniteRecyclerCalendarActivity::class.java)
49 | startActivity(intent)
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tejpratapsingh/recyclercalendaractivity/horizontal/HorizontalCalendarActivity.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendaractivity.horizontal
2 |
3 | import android.os.Bundle
4 | import android.widget.TextView
5 | import androidx.appcompat.app.AppCompatActivity
6 | import androidx.recyclerview.widget.PagerSnapHelper
7 | import androidx.recyclerview.widget.RecyclerView
8 | import com.tejpratapsingh.recyclercalendar.model.RecyclerCalendarConfiguration
9 | import com.tejpratapsingh.recyclercalendar.utilities.CalendarUtils
10 | import com.tejpratapsingh.recyclercalendaractivity.R
11 | import java.util.*
12 |
13 | class HorizontalCalendarActivity : AppCompatActivity() {
14 |
15 | override fun onCreate(savedInstanceState: Bundle?) {
16 | super.onCreate(savedInstanceState)
17 | setContentView(R.layout.activity_horizontal_calendar)
18 |
19 | val calendarRecyclerView: RecyclerView = findViewById(R.id.calendarRecyclerView)
20 | val textViewSelectedDate: TextView = findViewById(R.id.textViewSelectedDate)
21 |
22 | val date = Date()
23 | date.time = System.currentTimeMillis()
24 |
25 | val startCal = Calendar.getInstance()
26 |
27 | val endCal = Calendar.getInstance()
28 | endCal.time = date
29 | endCal.add(Calendar.MONTH, 3)
30 |
31 | val configuration: RecyclerCalendarConfiguration =
32 | RecyclerCalendarConfiguration(
33 | calenderViewType = RecyclerCalendarConfiguration.CalenderViewType.HORIZONTAL,
34 | calendarLocale = Locale.getDefault(),
35 | includeMonthHeader = true
36 | )
37 | configuration.weekStartOffset = RecyclerCalendarConfiguration.START_DAY_OF_WEEK.MONDAY
38 |
39 | textViewSelectedDate.text =
40 | CalendarUtils.dateStringFromFormat(
41 | locale = configuration.calendarLocale,
42 | date = date,
43 | format = CalendarUtils.LONG_DATE_FORMAT
44 | ) ?: ""
45 |
46 | val calendarAdapterHorizontal: HorizontalRecyclerCalendarAdapter =
47 | HorizontalRecyclerCalendarAdapter(
48 | startDate = startCal.time,
49 | endDate = endCal.time,
50 | configuration = configuration,
51 | selectedDate = date,
52 | dateSelectListener = object : HorizontalRecyclerCalendarAdapter.OnDateSelected {
53 | override fun onDateSelected(date: Date) {
54 | textViewSelectedDate.text =
55 | CalendarUtils.dateStringFromFormat(
56 | locale = configuration.calendarLocale,
57 | date = date,
58 | format = CalendarUtils.LONG_DATE_FORMAT
59 | )
60 | ?: ""
61 | }
62 | }
63 | )
64 |
65 | calendarRecyclerView.adapter = calendarAdapterHorizontal
66 |
67 | val snapHelper = PagerSnapHelper() // Or LinearSnapHelper
68 | snapHelper.attachToRecyclerView(calendarRecyclerView)
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tejpratapsingh/recyclercalendaractivity/horizontal/HorizontalRecyclerCalendarAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendaractivity.horizontal
2 |
3 | import android.content.Context
4 | import android.os.Build
5 | import android.view.LayoutInflater
6 | import android.view.View
7 | import android.view.ViewGroup
8 | import android.widget.TextView
9 | import androidx.core.content.ContextCompat
10 | import androidx.recyclerview.widget.RecyclerView
11 | import com.tejpratapsingh.recyclercalendar.adapter.RecyclerCalendarBaseAdapter
12 | import com.tejpratapsingh.recyclercalendar.model.RecyclerCalendarConfiguration
13 | import com.tejpratapsingh.recyclercalendar.model.RecyclerCalenderViewItem
14 | import com.tejpratapsingh.recyclercalendar.utilities.CalendarUtils
15 | import com.tejpratapsingh.recyclercalendaractivity.R
16 | import java.util.*
17 |
18 | class HorizontalRecyclerCalendarAdapter(
19 | startDate: Date,
20 | endDate: Date,
21 | private val configuration: RecyclerCalendarConfiguration,
22 | private var selectedDate: Date,
23 | private val dateSelectListener: OnDateSelected
24 | ) : RecyclerCalendarBaseAdapter(startDate, endDate, configuration) {
25 |
26 | interface OnDateSelected {
27 | fun onDateSelected(date: Date)
28 | }
29 |
30 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
31 | val view: View = LayoutInflater.from(parent.context)
32 | .inflate(R.layout.item_calendar_horizontal, parent, false)
33 | return MonthCalendarViewHolder(
34 | view
35 | )
36 | }
37 |
38 | override fun onBindViewHolder(
39 | holder: RecyclerView.ViewHolder,
40 | position: Int,
41 | calendarItem: RecyclerCalenderViewItem
42 | ) {
43 | val monthViewHolder: MonthCalendarViewHolder = holder as MonthCalendarViewHolder
44 | val context: Context = monthViewHolder.itemView.context
45 | monthViewHolder.itemView.visibility = View.VISIBLE
46 |
47 | monthViewHolder.itemView.setOnClickListener(null)
48 |
49 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
50 | monthViewHolder.itemView.background = null
51 | } else {
52 | monthViewHolder.itemView.setBackgroundDrawable(null)
53 | }
54 | monthViewHolder.textViewDay.setTextColor(
55 | ContextCompat.getColor(
56 | context,
57 | R.color.colorBlack
58 | )
59 | )
60 | monthViewHolder.textViewDate.setTextColor(
61 | ContextCompat.getColor(
62 | context,
63 | R.color.colorBlack
64 | )
65 | )
66 |
67 | if (calendarItem.isHeader) {
68 | val selectedCalendar = Calendar.getInstance()
69 | selectedCalendar.time = calendarItem.date
70 |
71 | val month: String = CalendarUtils.dateStringFromFormat(
72 | locale = configuration.calendarLocale,
73 | date = selectedCalendar.time,
74 | format = CalendarUtils.DISPLAY_MONTH_FORMAT
75 | ) ?: ""
76 | val year = selectedCalendar[Calendar.YEAR].toLong()
77 |
78 | monthViewHolder.textViewDay.text = year.toString()
79 | monthViewHolder.textViewDate.text = month
80 |
81 | monthViewHolder.itemView.setOnClickListener(null)
82 | } else if (calendarItem.isEmpty) {
83 | monthViewHolder.itemView.visibility = View.GONE
84 | monthViewHolder.textViewDay.text = ""
85 | monthViewHolder.textViewDate.text = ""
86 | } else {
87 | val calendarDate = Calendar.getInstance()
88 | calendarDate.time = calendarItem.date
89 |
90 | val stringCalendarTimeFormat: String =
91 | CalendarUtils.dateStringFromFormat(
92 | locale = configuration.calendarLocale,
93 | date = calendarItem.date,
94 | format = CalendarUtils.DB_DATE_FORMAT
95 | )
96 | ?: ""
97 | val stringSelectedTimeFormat: String =
98 | CalendarUtils.dateStringFromFormat(
99 | locale = configuration.calendarLocale,
100 | date = selectedDate,
101 | format = CalendarUtils.DB_DATE_FORMAT
102 | ) ?: ""
103 |
104 | if (stringCalendarTimeFormat == stringSelectedTimeFormat) {
105 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
106 | monthViewHolder.itemView.background =
107 | ContextCompat.getDrawable(context, R.drawable.layout_round_corner_filled)
108 | } else {
109 | monthViewHolder.itemView.setBackgroundDrawable(
110 | ContextCompat.getDrawable(
111 | context,
112 | R.drawable.layout_round_corner_filled
113 | )
114 | )
115 | }
116 | monthViewHolder.textViewDay.setTextColor(
117 | ContextCompat.getColor(
118 | context,
119 | R.color.colorWhite
120 | )
121 | )
122 | monthViewHolder.textViewDate.setTextColor(
123 | ContextCompat.getColor(
124 | context,
125 | R.color.colorWhite
126 | )
127 | )
128 | }
129 |
130 | val day: String = CalendarUtils.dateStringFromFormat(
131 | locale = configuration.calendarLocale,
132 | date = calendarDate.time,
133 | format = CalendarUtils.DISPLAY_WEEK_DAY_FORMAT
134 | ) ?: ""
135 |
136 | monthViewHolder.textViewDay.text = day
137 |
138 | monthViewHolder.textViewDate.text =
139 | CalendarUtils.dateStringFromFormat(
140 | locale = configuration.calendarLocale,
141 | date = calendarDate.time,
142 | format = CalendarUtils.DISPLAY_DATE_FORMAT
143 | ) ?: ""
144 |
145 | monthViewHolder.itemView.setOnClickListener {
146 | selectedDate = calendarItem.date
147 | dateSelectListener.onDateSelected(calendarItem.date)
148 | notifyDataSetChanged()
149 | }
150 | }
151 | }
152 |
153 | class MonthCalendarViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
154 | val textViewDay: TextView = itemView.findViewById(R.id.textCalenderItemHorizontalDay)
155 | val textViewDate: TextView = itemView.findViewById(R.id.textCalenderItemHorizontalDate)
156 | }
157 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/tejpratapsingh/recyclercalendaractivity/model/SimpleEvent.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendaractivity.model
2 |
3 | import java.util.*
4 |
5 | class SimpleEvent(val date: Date, val title: String, val color: Int, val progress: Int = 0)
--------------------------------------------------------------------------------
/app/src/main/java/com/tejpratapsingh/recyclercalendaractivity/simple/InfiniteRecyclerCalendarActivity.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendaractivity.simple
2 |
3 | import android.os.Bundle
4 | import android.view.View
5 | import android.widget.ImageButton
6 | import android.widget.LinearLayout
7 | import android.widget.RadioButton
8 | import android.widget.Toast
9 | import androidx.appcompat.app.AppCompatActivity
10 | import com.tejpratapsingh.recyclercalendar.adapter.InfiniteRecyclerCalenderAdapter
11 | import com.tejpratapsingh.recyclercalendar.model.InfiniteRecyclerCalendarConfiguration
12 | import com.tejpratapsingh.recyclercalendar.model.RecyclerCalendarConfiguration
13 | import com.tejpratapsingh.recyclercalendar.utilities.CalendarUtils
14 | import com.tejpratapsingh.recyclercalendar.views.InfiniteRecyclerCalendarView
15 | import com.tejpratapsingh.recyclercalendaractivity.R
16 | import java.util.*
17 |
18 | class InfiniteRecyclerCalendarActivity : AppCompatActivity() {
19 |
20 | private var calenderView: InfiniteRecyclerCalendarView? = null
21 | private var selectionMode: InfiniteRecyclerCalendarConfiguration.SelectionMode? = null
22 | private var calendarViewType: RecyclerCalendarConfiguration.CalenderViewType =
23 | RecyclerCalendarConfiguration.CalenderViewType.VERTICAL
24 |
25 | override fun onCreate(savedInstanceState: Bundle?) {
26 | super.onCreate(savedInstanceState)
27 | setContentView(R.layout.activity_infinite_recycler_calendar)
28 |
29 | calenderView = findViewById(R.id.calendarRecyclerView)
30 |
31 | val buttonSetting: ImageButton = findViewById(R.id.buttonSimpleSettings)
32 | val layoutSettingContainer: LinearLayout = findViewById(R.id.layoutSettingContainer)
33 |
34 | buttonSetting.setOnClickListener {
35 | if (layoutSettingContainer.visibility == View.VISIBLE) {
36 | layoutSettingContainer.visibility = View.GONE
37 | } else {
38 | layoutSettingContainer.visibility = View.VISIBLE
39 | }
40 | }
41 |
42 | val radioViewTypeVertical: RadioButton = findViewById(R.id.radioViewTypeVertical)
43 | val radioViewTypeHorizontal: RadioButton = findViewById(R.id.radioViewTypeHorizontal)
44 |
45 | radioViewTypeVertical.setOnClickListener {
46 | // Switch to Vertical View
47 | calendarViewType = RecyclerCalendarConfiguration.CalenderViewType.VERTICAL
48 |
49 | refreshCalendarCalendar()
50 | }
51 |
52 | radioViewTypeHorizontal.setOnClickListener {
53 | // Switch to Horizontal View
54 | calendarViewType = RecyclerCalendarConfiguration.CalenderViewType.HORIZONTAL
55 |
56 | refreshCalendarCalendar()
57 | }
58 |
59 | selectionMode = InfiniteRecyclerCalendarConfiguration.SelectionModeNone()
60 |
61 | refreshCalendarCalendar()
62 | }
63 |
64 | private fun refreshCalendarCalendar() {
65 | if (calenderView == null || selectionMode == null) {
66 | return
67 | }
68 | val configuration: InfiniteRecyclerCalendarConfiguration =
69 | InfiniteRecyclerCalendarConfiguration(
70 | calenderViewType = calendarViewType,
71 | calendarLocale = Locale.getDefault(),
72 | includeMonthHeader = true,
73 | selectionMode = selectionMode!!
74 | )
75 |
76 | configuration.weekStartOffset = RecyclerCalendarConfiguration.START_DAY_OF_WEEK.MONDAY
77 |
78 | calenderView!!.initialise(
79 | configuration,
80 | object : InfiniteRecyclerCalenderAdapter.OnDateSelected {
81 | override fun onDateSelected(date: Date) {
82 | Toast.makeText(
83 | calenderView!!.context,
84 | "Date Selected: ${CalendarUtils.getGmt(date)}",
85 | Toast.LENGTH_LONG
86 | ).show()
87 | }
88 | })
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tejpratapsingh/recyclercalendaractivity/simple/SimpleRecyclerCalendarActivity.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendaractivity.simple
2 |
3 | import android.os.Bundle
4 | import android.view.View
5 | import android.widget.ImageButton
6 | import android.widget.LinearLayout
7 | import android.widget.RadioButton
8 | import android.widget.Toast
9 | import androidx.appcompat.app.AppCompatActivity
10 | import com.tejpratapsingh.recyclercalendar.adapter.SimpleRecyclerCalendarAdapter
11 | import com.tejpratapsingh.recyclercalendar.model.RecyclerCalendarConfiguration
12 | import com.tejpratapsingh.recyclercalendar.model.SimpleRecyclerCalendarConfiguration
13 | import com.tejpratapsingh.recyclercalendar.utilities.CalendarUtils
14 | import com.tejpratapsingh.recyclercalendar.views.SimpleRecyclerCalendarView
15 | import com.tejpratapsingh.recyclercalendaractivity.R
16 | import java.util.*
17 | import kotlin.collections.HashMap
18 |
19 | class SimpleRecyclerCalendarActivity : AppCompatActivity() {
20 |
21 | private var calenderView: SimpleRecyclerCalendarView? = null
22 | private var selectionMode: SimpleRecyclerCalendarConfiguration.SelectionMode? = null
23 | private var calendarViewType: RecyclerCalendarConfiguration.CalenderViewType =
24 | RecyclerCalendarConfiguration.CalenderViewType.VERTICAL
25 |
26 | override fun onCreate(savedInstanceState: Bundle?) {
27 | super.onCreate(savedInstanceState)
28 | setContentView(R.layout.activity_simple_recycler_calendar)
29 |
30 | calenderView = findViewById(R.id.calendarRecyclerView)
31 |
32 | val date = Date()
33 | date.time = System.currentTimeMillis()
34 |
35 | val startCal = Calendar.getInstance()
36 |
37 | val endCal = Calendar.getInstance()
38 | endCal.time = date
39 | endCal.add(Calendar.MONTH, 3)
40 |
41 | val buttonSetting: ImageButton = findViewById(R.id.buttonSimpleSettings)
42 | val layoutSettingContainer: LinearLayout = findViewById(R.id.layoutSettingContainer)
43 |
44 | buttonSetting.setOnClickListener {
45 | if (layoutSettingContainer.visibility == View.VISIBLE) {
46 | layoutSettingContainer.visibility = View.GONE
47 | } else {
48 | layoutSettingContainer.visibility = View.VISIBLE
49 | }
50 | }
51 |
52 | val radioViewTypeVertical: RadioButton = findViewById(R.id.radioViewTypeVertical)
53 | val radioViewTypeHorizontal: RadioButton = findViewById(R.id.radioViewTypeHorizontal)
54 |
55 | val radioSelectNone: RadioButton = findViewById(R.id.radioSelectionNone)
56 | val radioSelectSingle: RadioButton = findViewById(R.id.radioSelectionSingle)
57 | val radioSelectMultiple: RadioButton = findViewById(R.id.radioSelectionMultiple)
58 | val radioSelectRange: RadioButton = findViewById(R.id.radioSelectionRange)
59 |
60 | radioViewTypeVertical.setOnClickListener {
61 | // Switch to Vertical View
62 | calendarViewType = RecyclerCalendarConfiguration.CalenderViewType.VERTICAL
63 |
64 | refreshCalendarCalendar(
65 | startDate = startCal.time,
66 | endDate = endCal.time
67 | )
68 | }
69 |
70 | radioViewTypeHorizontal.setOnClickListener {
71 | // Switch to Horizontal View
72 | calendarViewType = RecyclerCalendarConfiguration.CalenderViewType.HORIZONTAL
73 |
74 | refreshCalendarCalendar(
75 | startDate = startCal.time,
76 | endDate = endCal.time
77 | )
78 | }
79 |
80 | radioSelectNone.setOnClickListener {
81 | // Switch to Selection Mode NONE
82 | selectionMode = SimpleRecyclerCalendarConfiguration.SelectionModeNone()
83 |
84 | refreshCalendarCalendar(
85 | startDate = startCal.time,
86 | endDate = endCal.time
87 |
88 | )
89 | }
90 | radioSelectSingle.setOnClickListener {
91 | // Switch to Selection Mode SINGLE
92 | selectionMode =
93 | SimpleRecyclerCalendarConfiguration.SelectionModeSingle(selectedDate = Date())
94 |
95 | refreshCalendarCalendar(
96 | startDate = startCal.time,
97 | endDate = endCal.time
98 | )
99 | }
100 | radioSelectMultiple.setOnClickListener {
101 | // Switch to Selection Mode MULTIPLE
102 | selectionMode = SimpleRecyclerCalendarConfiguration.SelectionModeMultiple(
103 | selectionStartDateList = HashMap()
104 | )
105 |
106 | refreshCalendarCalendar(
107 | startDate = startCal.time,
108 | endDate = endCal.time
109 | )
110 | }
111 | radioSelectRange.setOnClickListener {
112 | // Switch to Selection Mode RANGE
113 |
114 | // Range Starts from todayDate and ends on 5 days from today
115 | val selectionEndCal = Calendar.getInstance()
116 | selectionEndCal.time = date
117 | selectionEndCal.add(Calendar.DATE, 5)
118 |
119 | selectionMode = SimpleRecyclerCalendarConfiguration.SelectionModeRange(
120 | selectionStartDate = date,
121 | selectionEndDate = selectionEndCal.time
122 | )
123 |
124 | refreshCalendarCalendar(
125 | startDate = startCal.time,
126 | endDate = endCal.time
127 | )
128 | }
129 |
130 | // Set None As Default
131 | radioSelectNone.callOnClick()
132 | }
133 |
134 | private fun refreshCalendarCalendar(
135 | startDate: Date,
136 | endDate: Date
137 | ) {
138 | val configuration: SimpleRecyclerCalendarConfiguration =
139 | SimpleRecyclerCalendarConfiguration(
140 | calenderViewType = calendarViewType,
141 | calendarLocale = Locale.getDefault(),
142 | includeMonthHeader = true,
143 | selectionMode = selectionMode!!
144 | )
145 | configuration.weekStartOffset = RecyclerCalendarConfiguration.START_DAY_OF_WEEK.MONDAY
146 |
147 | calenderView!!.initialise(
148 | startDate,
149 | endDate,
150 | configuration,
151 | object : SimpleRecyclerCalendarAdapter.OnDateSelected {
152 | override fun onDateSelected(date: Date) {
153 | Toast.makeText(
154 | calenderView!!.context,
155 | "Date Selected: ${CalendarUtils.getGmt(date)}",
156 | Toast.LENGTH_LONG
157 | ).show()
158 | }
159 | })
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tejpratapsingh/recyclercalendaractivity/vertical/VerticalCalendarActivity.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendaractivity.vertical
2 |
3 | import android.os.Bundle
4 | import androidx.appcompat.app.AlertDialog
5 | import androidx.appcompat.app.AppCompatActivity
6 | import androidx.core.content.ContextCompat
7 | import androidx.recyclerview.widget.RecyclerView
8 | import com.tejpratapsingh.recyclercalendar.model.RecyclerCalendarConfiguration
9 | import com.tejpratapsingh.recyclercalendar.utilities.CalendarUtils
10 | import com.tejpratapsingh.recyclercalendaractivity.R
11 | import com.tejpratapsingh.recyclercalendaractivity.model.SimpleEvent
12 | import java.util.*
13 | import kotlin.collections.HashMap
14 |
15 | class VerticalCalendarActivity : AppCompatActivity() {
16 |
17 | private val eventMap: HashMap = HashMap()
18 |
19 | override fun onCreate(savedInstanceState: Bundle?) {
20 | super.onCreate(savedInstanceState)
21 | setContentView(R.layout.activity_vertical_calendar)
22 |
23 | val calendarRecyclerView: RecyclerView = findViewById(R.id.calendarRecyclerView)
24 |
25 | val date = Date()
26 | date.time = System.currentTimeMillis()
27 |
28 | val startCal = Calendar.getInstance()
29 |
30 | val endCal = Calendar.getInstance()
31 | endCal.time = date
32 | endCal.add(Calendar.MONTH, 12)
33 |
34 | val configuration: RecyclerCalendarConfiguration =
35 | RecyclerCalendarConfiguration(
36 | calenderViewType = RecyclerCalendarConfiguration.CalenderViewType.VERTICAL,
37 | calendarLocale = Locale.getDefault(),
38 | includeMonthHeader = true
39 | )
40 |
41 | configuration.weekStartOffset = RecyclerCalendarConfiguration.START_DAY_OF_WEEK.MONDAY
42 |
43 | // Some Random Events
44 | for (i in 0..30 step 3) {
45 | val eventCal = Calendar.getInstance()
46 | eventCal.add(Calendar.DATE, i * 3)
47 | val eventDate: Int =
48 | (CalendarUtils.dateStringFromFormat(
49 | locale = configuration.calendarLocale,
50 | date = eventCal.time,
51 | format = CalendarUtils.DB_DATE_FORMAT
52 | )
53 | ?: "0").toInt()
54 | eventMap[eventDate] = SimpleEvent(
55 | eventCal.time,
56 | "Event #$i",
57 | ContextCompat.getColor(applicationContext, R.color.colorAccent)
58 | )
59 | }
60 |
61 | val calendarAdapterVertical: VerticalRecyclerCalendarAdapter =
62 | VerticalRecyclerCalendarAdapter(
63 | startDate = startCal.time,
64 | endDate = endCal.time,
65 | configuration = configuration,
66 | eventMap = eventMap,
67 | dateSelectListener = object : VerticalRecyclerCalendarAdapter.OnDateSelected {
68 | override fun onDateSelected(date: Date, event: SimpleEvent?) {
69 | val selectedDate: String =
70 | CalendarUtils.dateStringFromFormat(
71 | locale = configuration.calendarLocale,
72 | date = date,
73 | format = CalendarUtils.LONG_DATE_FORMAT
74 | )
75 | ?: ""
76 |
77 | if (event != null) {
78 | AlertDialog.Builder(this@VerticalCalendarActivity)
79 | .setTitle("Event Clicked")
80 | .setMessage(
81 | String.format(
82 | Locale.getDefault(),
83 | "Date: %s\n\nEvent: %s",
84 | selectedDate,
85 | event.title
86 | )
87 | )
88 | .create()
89 | .show()
90 | }
91 | }
92 | }
93 | );
94 |
95 | calendarRecyclerView.adapter = calendarAdapterVertical
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tejpratapsingh/recyclercalendaractivity/vertical/VerticalRecyclerCalendarAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendaractivity.vertical
2 |
3 | import android.view.LayoutInflater
4 | import android.view.View
5 | import android.view.ViewGroup
6 | import android.widget.TextView
7 | import androidx.recyclerview.widget.RecyclerView
8 | import com.tejpratapsingh.recyclercalendar.adapter.RecyclerCalendarBaseAdapter
9 | import com.tejpratapsingh.recyclercalendar.model.RecyclerCalendarConfiguration
10 | import com.tejpratapsingh.recyclercalendar.model.RecyclerCalenderViewItem
11 | import com.tejpratapsingh.recyclercalendar.utilities.CalendarUtils
12 | import com.tejpratapsingh.recyclercalendaractivity.R
13 | import com.tejpratapsingh.recyclercalendaractivity.model.SimpleEvent
14 | import java.util.*
15 |
16 | class VerticalRecyclerCalendarAdapter(
17 | startDate: Date,
18 | endDate: Date,
19 | val configuration: RecyclerCalendarConfiguration,
20 | val eventMap: HashMap,
21 | val dateSelectListener: OnDateSelected
22 | ) : RecyclerCalendarBaseAdapter(startDate, endDate, configuration) {
23 |
24 | interface OnDateSelected {
25 | fun onDateSelected(date: Date, event: SimpleEvent?)
26 | }
27 |
28 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
29 | val view: View = LayoutInflater.from(parent.context)
30 | .inflate(R.layout.item_calendar_vertical, parent, false)
31 | return MonthCalendarViewHolder(
32 | view
33 | )
34 | }
35 |
36 | override fun onBindViewHolder(
37 | holder: RecyclerView.ViewHolder,
38 | position: Int,
39 | calendarItem: RecyclerCalenderViewItem
40 | ) {
41 | val monthViewHolder: MonthCalendarViewHolder = holder as MonthCalendarViewHolder
42 | monthViewHolder.itemView.visibility = View.VISIBLE
43 | monthViewHolder.viewEvent.visibility = View.GONE
44 |
45 | monthViewHolder.itemView.setOnClickListener(null)
46 |
47 | if (calendarItem.isHeader) {
48 | val selectedCalendar = Calendar.getInstance(Locale.getDefault())
49 | selectedCalendar.time = calendarItem.date
50 |
51 | val month: String = CalendarUtils.dateStringFromFormat(
52 | locale = configuration.calendarLocale,
53 | date = selectedCalendar.time,
54 | format = CalendarUtils.DISPLAY_MONTH_FORMAT
55 | ) ?: ""
56 | val year = selectedCalendar[Calendar.YEAR].toLong()
57 |
58 | monthViewHolder.textViewDay.text = year.toString()
59 | monthViewHolder.textViewDate.text = month
60 | } else if (calendarItem.isEmpty) {
61 | monthViewHolder.itemView.visibility = View.GONE
62 | monthViewHolder.textViewDay.text = ""
63 | monthViewHolder.textViewDate.text = ""
64 | } else {
65 | val calendarDate = Calendar.getInstance(Locale.getDefault())
66 | calendarDate.time = calendarItem.date
67 |
68 | val day: String = CalendarUtils.dateStringFromFormat(
69 | locale = configuration.calendarLocale,
70 | date = calendarDate.time,
71 | format = CalendarUtils.DISPLAY_WEEK_DAY_FORMAT
72 | ) ?: ""
73 |
74 | monthViewHolder.textViewDay.text = day
75 |
76 | val dateInt: Int =
77 | (CalendarUtils.dateStringFromFormat(
78 | locale = configuration.calendarLocale,
79 | date = calendarDate.time,
80 | format = CalendarUtils.DB_DATE_FORMAT
81 | )
82 | ?: "0").toInt()
83 |
84 | if (eventMap.contains(dateInt)) {
85 | monthViewHolder.viewEvent.visibility = View.VISIBLE
86 | monthViewHolder.viewEvent.setBackgroundColor(eventMap.get(dateInt)!!.color)
87 | }
88 |
89 | monthViewHolder.textViewDate.text =
90 | CalendarUtils.dateStringFromFormat(
91 | locale = configuration.calendarLocale,
92 | date = calendarDate.time,
93 | format = CalendarUtils.DISPLAY_DATE_FORMAT
94 | ) ?: ""
95 |
96 | monthViewHolder.itemView.setOnClickListener {
97 | dateSelectListener.onDateSelected(calendarItem.date, eventMap[dateInt])
98 | }
99 | }
100 | }
101 |
102 | class MonthCalendarViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
103 | val textViewDay: TextView = itemView.findViewById(R.id.textCalenderItemVerticalDay)
104 | val textViewDate: TextView = itemView.findViewById(R.id.textCalenderItemVerticalDate)
105 | val viewEvent: View = itemView.findViewById(R.id.viewCalenderItemVerticalEvent)
106 | }
107 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/tejpratapsingh/recyclercalendaractivity/viewpager/ViewPagerCalendarActivity.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendaractivity.viewpager
2 |
3 | import android.os.Build
4 | import android.os.Bundle
5 | import android.view.View
6 | import androidx.appcompat.app.AppCompatActivity
7 | import androidx.viewpager.widget.ViewPager
8 | import com.google.android.material.tabs.TabLayout
9 | import com.tejpratapsingh.recyclercalendaractivity.R
10 | import com.tejpratapsingh.recyclercalendaractivity.viewpager.ui.main.SectionsPagerAdapter
11 |
12 | class ViewPagerCalendarActivity : AppCompatActivity() {
13 |
14 | override fun onCreate(savedInstanceState: Bundle?) {
15 | super.onCreate(savedInstanceState)
16 | setContentView(R.layout.activity_view_pager_calendar)
17 |
18 | val sectionsPagerAdapter = SectionsPagerAdapter(this, supportFragmentManager)
19 | val viewPager: ViewPager = findViewById(R.id.view_pager)
20 | viewPager.adapter = sectionsPagerAdapter
21 | val tabs: TabLayout = findViewById(R.id.tabs)
22 | tabs.setupWithViewPager(viewPager)
23 |
24 | val config = resources.configuration
25 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
26 | if (config.layoutDirection == View.LAYOUT_DIRECTION_RTL) {
27 | // showAlertMsg("LTR")
28 | tabs.layoutDirection = View.LAYOUT_DIRECTION_LTR;
29 | }
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/tejpratapsingh/recyclercalendaractivity/viewpager/ViewPagerRecyclerCalendarAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendaractivity.viewpager
2 |
3 | import android.view.LayoutInflater
4 | import android.view.View
5 | import android.view.ViewGroup
6 | import android.widget.ProgressBar
7 | import android.widget.TextView
8 | import androidx.recyclerview.widget.RecyclerView
9 | import com.tejpratapsingh.recyclercalendar.adapter.RecyclerCalendarBaseAdapter
10 | import com.tejpratapsingh.recyclercalendar.model.RecyclerCalendarConfiguration
11 | import com.tejpratapsingh.recyclercalendar.model.RecyclerCalenderViewItem
12 | import com.tejpratapsingh.recyclercalendar.utilities.CalendarUtils
13 | import com.tejpratapsingh.recyclercalendaractivity.R
14 | import com.tejpratapsingh.recyclercalendaractivity.model.SimpleEvent
15 | import java.util.*
16 |
17 | class ViewPagerRecyclerCalendarAdapter(
18 | startDate: Date,
19 | endDate: Date,
20 | val configuration: RecyclerCalendarConfiguration,
21 | val eventMap: HashMap,
22 | val dateSelectListener: ViewPagerRecyclerCalendarAdapter.OnDateSelected
23 | ) : RecyclerCalendarBaseAdapter(startDate, endDate, configuration) {
24 |
25 | interface OnDateSelected {
26 | fun onDateSelected(date: Date, event: SimpleEvent?)
27 | }
28 |
29 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
30 | val view: View = LayoutInflater.from(parent.context)
31 | .inflate(R.layout.item_calendar_view_pager, parent, false)
32 | return MonthCalendarViewHolder(
33 | view
34 | )
35 | }
36 |
37 | override fun onBindViewHolder(
38 | holder: RecyclerView.ViewHolder,
39 | position: Int,
40 | calendarItem: RecyclerCalenderViewItem
41 | ) {
42 | val monthViewHolder: MonthCalendarViewHolder = holder as MonthCalendarViewHolder
43 | monthViewHolder.itemView.visibility = View.VISIBLE
44 | monthViewHolder.progressBar.visibility = View.GONE
45 |
46 | if (calendarItem.isHeader) {
47 | val selectedCalendar = Calendar.getInstance(Locale.getDefault())
48 | selectedCalendar.time = calendarItem.date
49 |
50 | val month: String = CalendarUtils.dateStringFromFormat(
51 | locale = configuration.calendarLocale,
52 | date = selectedCalendar.time,
53 | format = CalendarUtils.DISPLAY_MONTH_FORMAT
54 | ) ?: ""
55 | val year = selectedCalendar[Calendar.YEAR].toLong()
56 |
57 | monthViewHolder.textViewDay.text = year.toString()
58 | monthViewHolder.textViewDate.text = month
59 | } else if (calendarItem.isEmpty) {
60 | monthViewHolder.itemView.visibility = View.GONE
61 | monthViewHolder.textViewDay.text = ""
62 | monthViewHolder.textViewDate.text = ""
63 | } else {
64 | val calendarDate = Calendar.getInstance(Locale.getDefault())
65 | calendarDate.time = calendarItem.date
66 |
67 | val day: String = CalendarUtils.dateStringFromFormat(
68 | locale = configuration.calendarLocale,
69 | date = calendarDate.time,
70 | format = CalendarUtils.DISPLAY_WEEK_DAY_FORMAT
71 | ) ?: ""
72 |
73 | val dateInt: Int =
74 | (CalendarUtils.dateStringFromFormat(
75 | locale = configuration.calendarLocale,
76 | date = calendarDate.time,
77 | format = CalendarUtils.DB_DATE_FORMAT
78 | )
79 | ?: "0").toInt()
80 |
81 | if (eventMap.contains(dateInt)) {
82 | monthViewHolder.progressBar.visibility = View.VISIBLE
83 | monthViewHolder.progressBar.progress = eventMap.get(dateInt)!!.progress
84 | }
85 |
86 | monthViewHolder.textViewDay.text = day
87 |
88 | monthViewHolder.textViewDate.text =
89 | CalendarUtils.dateStringFromFormat(
90 | locale = configuration.calendarLocale,
91 | date = calendarDate.time,
92 | format = CalendarUtils.DISPLAY_DATE_FORMAT
93 | ) ?: ""
94 |
95 | monthViewHolder.itemView.setOnClickListener {
96 | dateSelectListener.onDateSelected(calendarItem.date, eventMap[dateInt])
97 | }
98 | }
99 | }
100 |
101 | class MonthCalendarViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
102 | val textViewDay: TextView = itemView.findViewById(R.id.textCalenderItemViewPagerDay)
103 | val textViewDate: TextView = itemView.findViewById(R.id.textCalenderItemViewPagerDate)
104 | val progressBar: ProgressBar = itemView.findViewById(R.id.progressBarCalenderItemViewPager);
105 | }
106 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/tejpratapsingh/recyclercalendaractivity/viewpager/ui/main/PlaceholderFragment.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendaractivity.viewpager.ui.main
2 |
3 | import android.os.Bundle
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import androidx.appcompat.app.AlertDialog
8 | import androidx.core.content.ContextCompat
9 | import androidx.fragment.app.Fragment
10 | import androidx.recyclerview.widget.RecyclerView
11 | import com.tejpratapsingh.recyclercalendar.model.RecyclerCalendarConfiguration
12 | import com.tejpratapsingh.recyclercalendar.utilities.CalendarUtils
13 | import com.tejpratapsingh.recyclercalendaractivity.R
14 | import com.tejpratapsingh.recyclercalendaractivity.model.SimpleEvent
15 | import com.tejpratapsingh.recyclercalendaractivity.viewpager.ViewPagerRecyclerCalendarAdapter
16 | import java.util.*
17 |
18 | /**
19 | * A placeholder fragment containing a simple view.
20 | */
21 | class PlaceholderFragment : Fragment() {
22 |
23 | private val eventMap: HashMap = HashMap()
24 |
25 | override fun onCreateView(
26 | inflater: LayoutInflater, container: ViewGroup?,
27 | savedInstanceState: Bundle?
28 | ): View? {
29 | val root = inflater.inflate(R.layout.fragment_view_pager_calendar, container, false)
30 | val sectionNumber: Int = requireArguments().get(ARG_SECTION_NUMBER) as Int
31 | val calendarRecyclerView: RecyclerView = root.findViewById(R.id.calendarRecyclerView)
32 | val date = Date()
33 | date.time = System.currentTimeMillis()
34 |
35 | val startCal = Calendar.getInstance()
36 | startCal.time = date
37 | startCal.add(Calendar.MONTH, sectionNumber)
38 |
39 | val configuration: RecyclerCalendarConfiguration =
40 | RecyclerCalendarConfiguration(
41 | calenderViewType = RecyclerCalendarConfiguration.CalenderViewType.VERTICAL,
42 | calendarLocale = Locale.getDefault(),
43 | includeMonthHeader = false
44 | )
45 | configuration.weekStartOffset = RecyclerCalendarConfiguration.START_DAY_OF_WEEK.MONDAY
46 |
47 | // Some Random Events
48 | for (i in 0..30 step 3) {
49 | val eventCal = Calendar.getInstance()
50 | eventCal.add(Calendar.DATE, i * 3)
51 | val eventDate: Int =
52 | (CalendarUtils.dateStringFromFormat(
53 | locale = configuration.calendarLocale,
54 | date = eventCal.time,
55 | format = CalendarUtils.DB_DATE_FORMAT
56 | )
57 | ?: "0").toInt()
58 | eventMap[eventDate] = SimpleEvent(
59 | date = eventCal.time,
60 | title = "Event #$i",
61 | color = ContextCompat.getColor(root.context, R.color.colorAccent),
62 | progress = i * 3
63 | )
64 | }
65 |
66 | val calendarAdapterViewPager: ViewPagerRecyclerCalendarAdapter =
67 | ViewPagerRecyclerCalendarAdapter(
68 | startDate = startCal.time,
69 | endDate = startCal.time,
70 | configuration = configuration,
71 | eventMap = eventMap,
72 | dateSelectListener = object : ViewPagerRecyclerCalendarAdapter.OnDateSelected {
73 | override fun onDateSelected(date: Date, event: SimpleEvent?) {
74 | val selectedDate: String =
75 | CalendarUtils.dateStringFromFormat(
76 | locale = configuration.calendarLocale,
77 | date = date,
78 | format = CalendarUtils.LONG_DATE_FORMAT
79 | )
80 | ?: ""
81 |
82 | if (event != null) {
83 | AlertDialog.Builder(activity!!)
84 | .setTitle("Event Clicked")
85 | .setMessage(
86 | String.format(
87 | Locale.getDefault(),
88 | "Date: %s\n\nEvent: %s\n\nProgress: %s",
89 | selectedDate,
90 | event.title,
91 | event.progress
92 | )
93 | )
94 | .create()
95 | .show()
96 | }
97 | }
98 | }
99 | )
100 |
101 | calendarRecyclerView.adapter = calendarAdapterViewPager
102 | return root
103 | }
104 |
105 | companion object {
106 | /**
107 | * The fragment argument representing the section number for this
108 | * fragment.
109 | */
110 | private const val ARG_SECTION_NUMBER = "section_number"
111 |
112 | /**
113 | * Returns a new instance of this fragment for the given section
114 | * number.
115 | */
116 | @JvmStatic
117 | fun newInstance(sectionNumber: Int): PlaceholderFragment {
118 | return PlaceholderFragment().apply {
119 | arguments = Bundle().apply {
120 | putInt(ARG_SECTION_NUMBER, sectionNumber)
121 | }
122 | }
123 | }
124 | }
125 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/tejpratapsingh/recyclercalendaractivity/viewpager/ui/main/SectionsPagerAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendaractivity.viewpager.ui.main
2 |
3 | import android.content.Context
4 | import androidx.fragment.app.Fragment
5 | import androidx.fragment.app.FragmentManager
6 | import androidx.fragment.app.FragmentPagerAdapter
7 | import com.tejpratapsingh.recyclercalendar.utilities.CalendarUtils
8 | import java.util.*
9 |
10 | /**
11 | * A [FragmentPagerAdapter] that returns a fragment corresponding to
12 | * one of the sections/tabs/pages.
13 | */
14 | class SectionsPagerAdapter(private val context: Context, fm: FragmentManager) :
15 | FragmentPagerAdapter(fm, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
16 |
17 | override fun getItem(position: Int): Fragment {
18 | // getItem is called to instantiate the fragment for the given page.
19 | // Return a PlaceholderFragment (defined as a static inner class below).
20 | return PlaceholderFragment.newInstance(position)
21 | }
22 |
23 | override fun getPageTitle(position: Int): CharSequence? {
24 | val date = Date()
25 | date.time = System.currentTimeMillis()
26 | val selectedCalendar = Calendar.getInstance(Locale.getDefault())
27 | selectedCalendar.time = date
28 | selectedCalendar.add(Calendar.MONTH, position)
29 |
30 | val month: String = CalendarUtils.dateStringFromFormat(
31 | locale = Locale.getDefault(),
32 | date = selectedCalendar.time,
33 | format = CalendarUtils.DISPLAY_MONTH_FORMAT
34 | ) ?: ""
35 | val year = selectedCalendar[Calendar.YEAR].toLong()
36 |
37 | return String.format(Locale.getDefault(), "%s / %d", month, year)
38 | }
39 |
40 | override fun getCount(): Int {
41 | // Show total pages.
42 | return 24
43 | }
44 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-anydpi/ic_action_setting.xml:
--------------------------------------------------------------------------------
1 |
8 |
10 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_action_setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/res/drawable-hdpi/ic_action_setting.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_action_setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/res/drawable-mdpi/ic_action_setting.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_action_setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/res/drawable-xhdpi/ic_action_setting.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_action_setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/res/drawable-xxhdpi/ic_action_setting.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/circle_shape.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/circular_progress_bar.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
10 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_calendar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/res/drawable/ic_calendar.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
9 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/layout_round_corner.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/layout_round_corner_filled.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_horizontal_calendar.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
19 |
20 |
25 |
26 |
32 |
33 |
38 |
39 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_infinite_recycler_calendar.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
26 |
27 |
34 |
35 |
36 |
41 |
42 |
51 |
52 |
57 |
58 |
64 |
65 |
70 |
71 |
72 |
73 |
74 |
78 |
79 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
23 |
24 |
32 |
33 |
39 |
40 |
52 |
53 |
54 |
55 |
63 |
64 |
70 |
71 |
83 |
84 |
85 |
93 |
94 |
100 |
101 |
113 |
114 |
115 |
124 |
125 |
133 |
134 |
140 |
141 |
153 |
154 |
155 |
163 |
164 |
170 |
171 |
183 |
184 |
185 |
195 |
196 |
197 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_simple_recycler_calendar.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
25 |
26 |
33 |
34 |
35 |
40 |
41 |
50 |
51 |
56 |
57 |
63 |
64 |
69 |
70 |
71 |
72 |
81 |
82 |
88 |
89 |
95 |
96 |
101 |
102 |
107 |
108 |
113 |
114 |
115 |
116 |
117 |
121 |
122 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_vertical_calendar.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
19 |
20 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_view_pager_calendar.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
20 |
21 |
30 |
31 |
36 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_view_pager_calendar.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_calendar_horizontal.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
16 |
17 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_calendar_vertical.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
20 |
21 |
29 |
30 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_calendar_view_pager.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
19 |
20 |
26 |
27 |
34 |
35 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #536DFE
6 | #C5CAE9
7 | #212121
8 | #757575
9 | #FFFFFF
10 | #BDBDBD
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 16dp
6 | 16dp
7 | 8dp
8 | 20sp
9 | 16sp
10 | 8dp
11 | 32sp
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Recycler Calendar Example
3 | Week Calendar
4 | Month Calendar
5 | Page Calendar
6 | Selected Date
7 | Simple Calendar
8 | Example
9 | Selection Mode
10 | None
11 | Single
12 | Multiple
13 | Range
14 | Vertical
15 | Horizontal
16 | Calendar Icon made by Freepik from www.flaticon.com
17 | Infinite Calendar
18 | Orientation
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/test/java/com/tejpratapsingh/recyclercalendaractivity/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendaractivity
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(2, 2)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.5.21'
5 | repositories {
6 | google()
7 | mavenCentral()
8 |
9 | }
10 | dependencies {
11 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
12 | classpath 'com.android.tools.build:gradle:7.0.2'
13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
14 | // NOTE: Do not place your application dependencies here; they belong
15 | // in the individual module build.gradle files
16 | }
17 | }
18 |
19 | allprojects {
20 | repositories {
21 | google()
22 | mavenCentral()
23 | }
24 | }
25 |
26 | task clean(type: Delete) {
27 | delete rootProject.buildDir
28 | }
29 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 | # Kotlin code style for this project: "official" or "obsolete":
21 | kotlin.code.style=official
22 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Oct 26 13:24:08 IST 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/jitpack.yml:
--------------------------------------------------------------------------------
1 | jdk:
2 | - openjdk11
--------------------------------------------------------------------------------
/recyclercalendar/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/recyclercalendar/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.library'
3 | id 'kotlin-android'
4 | id 'maven-publish'
5 | }
6 |
7 | group = 'com.github.tejpratap46'
8 | version = '2.0'
9 |
10 | android {
11 | compileSdkVersion 30
12 |
13 | defaultConfig {
14 | minSdkVersion 15
15 | targetSdkVersion 30
16 |
17 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
18 | consumerProguardFiles 'consumer-rules.pro'
19 | }
20 |
21 | buildTypes {
22 | release {
23 | minifyEnabled false
24 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
25 | }
26 | }
27 |
28 | }
29 |
30 | dependencies {
31 | implementation fileTree(dir: 'libs', include: ['*.jar'])
32 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
33 | implementation 'androidx.appcompat:appcompat:1.3.1'
34 | implementation 'androidx.recyclerview:recyclerview:1.2.1'
35 | implementation 'androidx.core:core-ktx:1.6.0'
36 | testImplementation 'junit:junit:4.13.2'
37 | androidTestImplementation 'androidx.test.ext:junit:1.1.3'
38 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
39 | }
40 |
41 | afterEvaluate {
42 | publishing {
43 | publications {
44 | // Creates a Maven publication called "release".
45 | release(MavenPublication) {
46 | from components.release
47 | groupId = 'com.github.tejpratap46'
48 | artifactId = 'recyclercalendar'
49 | version = '2.0'
50 | }
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/recyclercalendar/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/recyclercalendar/consumer-rules.pro
--------------------------------------------------------------------------------
/recyclercalendar/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/recyclercalendar/src/androidTest/java/com/tejpratapsingh/recyclercalendar/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendar
2 |
3 | import androidx.test.platform.app.InstrumentationRegistry
4 | import androidx.test.ext.junit.runners.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22 | assertEquals("com.tejpratapsingh.recyclercalendar.test", appContext.packageName)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/recyclercalendar/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/recyclercalendar/src/main/java/com/tejpratapsingh/recyclercalendar/adapter/InfiniteRecyclerCalenderAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendar.adapter
2 |
3 | import android.util.Log
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import androidx.recyclerview.widget.LinearLayoutManager
8 | import androidx.recyclerview.widget.PagerSnapHelper
9 | import androidx.recyclerview.widget.RecyclerView
10 | import androidx.recyclerview.widget.SnapHelper
11 | import com.tejpratapsingh.recyclercalendar.R
12 | import com.tejpratapsingh.recyclercalendar.model.InfiniteRecyclerCalendarConfiguration
13 | import com.tejpratapsingh.recyclercalendar.model.RecyclerCalendarConfiguration
14 | import com.tejpratapsingh.recyclercalendar.model.SimpleRecyclerCalendarConfiguration
15 | import com.tejpratapsingh.recyclercalendar.utilities.CalendarUtils
16 | import com.tejpratapsingh.recyclercalendar.views.SimpleRecyclerCalendarView
17 | import java.util.*
18 |
19 | class InfiniteRecyclerCalenderAdapter(
20 | private val dateSelectListener: OnDateSelected,
21 | private val configuration: InfiniteRecyclerCalendarConfiguration
22 | ) :
23 | RecyclerView.Adapter() {
24 | private val TAG = "InfiniteRecyclerCalende"
25 |
26 | private val viewPool: RecyclerView.RecycledViewPool = RecyclerView.RecycledViewPool()
27 |
28 | interface OnDateSelected {
29 | fun onDateSelected(date: Date)
30 | }
31 |
32 | private var snapHelper: SnapHelper = PagerSnapHelper()
33 |
34 | override fun onCreateViewHolder(
35 | parent: ViewGroup,
36 | viewType: Int
37 | ): InfiniteViewHolder {
38 | val view: View = LayoutInflater.from(parent.context)
39 | .inflate(R.layout.item_infinite_calendar, parent, false)
40 | return InfiniteViewHolder(itemView = view)
41 | }
42 |
43 | override fun getItemCount(): Int {
44 | return Int.MAX_VALUE
45 | }
46 |
47 | override fun onBindViewHolder(
48 | holder: InfiniteViewHolder,
49 | position: Int
50 | ) {
51 | val midPosition: Int = Int.MAX_VALUE / 2
52 | val currentMonth: Int = position - midPosition
53 |
54 | val startCal: Calendar = Calendar.getInstance(configuration.calendarLocale)
55 | startCal.add(Calendar.MONTH, currentMonth)
56 | startCal.set(Calendar.DATE, 1)
57 |
58 | val endCal: Calendar = Calendar.getInstance(configuration.calendarLocale)
59 | endCal.time = startCal.time
60 | endCal.add(Calendar.MONTH, 1)
61 | endCal.add(Calendar.DATE, -1)
62 |
63 | // Convert InfiniteRecyclerCalendarConfiguration TO SimpleRecyclerCalendarConfiguration
64 | val selectionMode: SimpleRecyclerCalendarConfiguration.SelectionMode =
65 | when (configuration.selectionMode) {
66 | is InfiniteRecyclerCalendarConfiguration.SelectionModeNone -> {
67 | SimpleRecyclerCalendarConfiguration.SelectionModeNone()
68 | }
69 | else -> {
70 | SimpleRecyclerCalendarConfiguration.SelectionModeNone()
71 | }
72 | }
73 |
74 | val simpleRecyclerCalendarConfiguration: SimpleRecyclerCalendarConfiguration =
75 | SimpleRecyclerCalendarConfiguration(
76 | calenderViewType = RecyclerCalendarConfiguration.CalenderViewType.VERTICAL,
77 | calendarLocale = configuration.calendarLocale,
78 | includeMonthHeader = configuration.includeMonthHeader,
79 | selectionMode = selectionMode
80 | )
81 | simpleRecyclerCalendarConfiguration.weekStartOffset = configuration.weekStartOffset
82 |
83 | holder.simpleRecyclerCalendarView.setRecycledViewPool(this.viewPool)
84 | holder.simpleRecyclerCalendarView.initialise(
85 | startDate = startCal.time,
86 | endDate = endCal.time,
87 | configuration = simpleRecyclerCalendarConfiguration,
88 | dateSelectListener = object : SimpleRecyclerCalendarAdapter.OnDateSelected {
89 | override fun onDateSelected(date: Date) {
90 | val currentDateString: String =
91 | CalendarUtils.dateStringFromFormat(
92 | locale = configuration.calendarLocale,
93 | date = date,
94 | format = CalendarUtils.DB_DATE_FORMAT
95 | )
96 | ?: ""
97 |
98 | Log.d(TAG, "onDateSelected: $currentDateString")
99 |
100 | dateSelectListener.onDateSelected(date)
101 | }
102 | })
103 | }
104 |
105 | class InfiniteViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
106 | val simpleRecyclerCalendarView: SimpleRecyclerCalendarView =
107 | itemView.findViewById(R.id.simpleCalenderRecyclerView)
108 | }
109 |
110 | /**
111 | * Set LayoutManager of recycler view to GridLayoutManager with span of 7 (week)
112 | */
113 | override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
114 | super.onAttachedToRecyclerView(recyclerView)
115 |
116 | if (configuration.calenderViewType == RecyclerCalendarConfiguration.CalenderViewType.HORIZONTAL) {
117 | recyclerView.layoutManager = LinearLayoutManager(
118 | recyclerView.context,
119 | LinearLayoutManager.HORIZONTAL,
120 | false
121 | )
122 |
123 | recyclerView.onFlingListener = null
124 |
125 | snapHelper = PagerSnapHelper() // Or LinearSnapHelper
126 | snapHelper.attachToRecyclerView(recyclerView)
127 | } else {
128 | recyclerView.layoutManager = LinearLayoutManager(
129 | recyclerView.context,
130 | LinearLayoutManager.VERTICAL,
131 | false
132 | )
133 |
134 | recyclerView.onFlingListener = null
135 |
136 | snapHelper.attachToRecyclerView(null)
137 | }
138 | }
139 | }
--------------------------------------------------------------------------------
/recyclercalendar/src/main/java/com/tejpratapsingh/recyclercalendar/adapter/RecyclerCalendarBaseAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendar.adapter
2 |
3 | import android.os.Handler
4 | import android.os.HandlerThread
5 | import androidx.recyclerview.widget.GridLayoutManager
6 | import androidx.recyclerview.widget.LinearLayoutManager
7 | import androidx.recyclerview.widget.RecyclerView
8 | import com.tejpratapsingh.recyclercalendar.model.RecyclerCalendarConfiguration
9 | import com.tejpratapsingh.recyclercalendar.model.RecyclerCalenderViewItem
10 | import java.util.*
11 |
12 |
13 | abstract class RecyclerCalendarBaseAdapter(
14 | startDate: Date,
15 | endDate: Date,
16 | private val configuration: RecyclerCalendarConfiguration
17 | ) : RecyclerView.Adapter() {
18 |
19 | var mHandlerThread: MyHandlerThread =
20 | MyHandlerThread(
21 | RecyclerCalendarBaseAdapter::class.java.simpleName
22 | )
23 | private val handler = Handler()
24 |
25 | private var calendarItemList: LinkedList = LinkedList()
26 |
27 | init {
28 | val startCalendar = Calendar.getInstance(configuration.calendarLocale)
29 | val endCalendar = Calendar.getInstance(configuration.calendarLocale)
30 | if (configuration.calenderViewType == RecyclerCalendarConfiguration.CalenderViewType.HORIZONTAL) {
31 | startCalendar.time = startDate
32 | var thisDayOfWeek: Int = startCalendar.get(Calendar.DAY_OF_WEEK)
33 | thisDayOfWeek += configuration.weekStartOffset.offset
34 |
35 | if (thisDayOfWeek - 1 < 0) {
36 | thisDayOfWeek = 7 + (thisDayOfWeek - 1)
37 | startCalendar.add(Calendar.DATE, -1 * thisDayOfWeek)
38 | } else {
39 | startCalendar.add(Calendar.DATE, -1 * (thisDayOfWeek - 1))
40 | }
41 | startCalendar[Calendar.HOUR_OF_DAY] = 0
42 | startCalendar[Calendar.MINUTE] = 0
43 | startCalendar[Calendar.SECOND] = 0
44 | startCalendar[Calendar.MILLISECOND] = 0
45 |
46 | endCalendar.time = endDate
47 | endCalendar[Calendar.DAY_OF_MONTH] = endCalendar.getActualMaximum(Calendar.DAY_OF_MONTH)
48 | endCalendar[Calendar.HOUR_OF_DAY] = 0
49 | endCalendar[Calendar.MINUTE] = 0
50 | endCalendar[Calendar.SECOND] = 0
51 | endCalendar[Calendar.MILLISECOND] = 0
52 | } else {
53 | startCalendar.time = startDate
54 | startCalendar[Calendar.DAY_OF_MONTH] = 1
55 | startCalendar[Calendar.HOUR_OF_DAY] = 0
56 | startCalendar[Calendar.MINUTE] = 0
57 | startCalendar[Calendar.SECOND] = 0
58 | startCalendar[Calendar.MILLISECOND] = 0
59 |
60 | endCalendar.time = endDate
61 | endCalendar[Calendar.DAY_OF_MONTH] = endCalendar.getActualMaximum(Calendar.DAY_OF_MONTH)
62 | endCalendar[Calendar.HOUR_OF_DAY] = 0
63 | endCalendar[Calendar.MINUTE] = 0
64 | endCalendar[Calendar.SECOND] = 0
65 | endCalendar[Calendar.MILLISECOND] = 0
66 | }
67 |
68 | val runnable = Runnable {
69 | while (startCalendar.time.before(endCalendar.time) || startCalendar.time == endCalendar.time) {
70 | val dayOfMonth: Int = startCalendar.get(Calendar.DAY_OF_MONTH)
71 | var dayOfWeek: Int = startCalendar.get(Calendar.DAY_OF_WEEK)
72 | dayOfWeek += configuration.weekStartOffset.offset
73 |
74 | if (configuration.calenderViewType == RecyclerCalendarConfiguration.CalenderViewType.VERTICAL && dayOfMonth == 1) { // First Day of month
75 | if (configuration.includeMonthHeader) {
76 | val calendarEmptyHeader: RecyclerCalenderViewItem =
77 | RecyclerCalenderViewItem(
78 | date = startCalendar.time,
79 | spanSize = 7,
80 | isEmpty = false,
81 | isHeader = true
82 | )
83 | calendarItemList.add(calendarEmptyHeader)
84 | }
85 |
86 | val calendarEmptyWeek: RecyclerCalenderViewItem =
87 | RecyclerCalenderViewItem(
88 | date = startCalendar.time,
89 | spanSize = 1,
90 | isEmpty = true,
91 | isHeader = false
92 | )
93 | if (dayOfWeek - 1 < 0) {
94 | dayOfWeek = 7 + (dayOfWeek - 1)
95 | calendarEmptyWeek.spanSize = dayOfWeek
96 | } else {
97 | calendarEmptyWeek.spanSize = dayOfWeek - 1
98 | }
99 | if (calendarEmptyWeek.spanSize > 0) {
100 | // Is span size is greater then 0, then add empty cell
101 | calendarItemList.add(calendarEmptyWeek)
102 | }
103 | }
104 | val calendarDateItem: RecyclerCalenderViewItem =
105 | RecyclerCalenderViewItem(
106 | date = startCalendar.time,
107 | spanSize = 1,
108 | isEmpty = false,
109 | isHeader = false
110 | )
111 | calendarItemList.add(calendarDateItem)
112 | startCalendar.add(Calendar.DATE, 1)
113 | }
114 | handler.post(Runnable {
115 | notifyDataSetChanged()
116 | })
117 | }
118 |
119 | mHandlerThread.start()
120 | mHandlerThread.prepareHandler()
121 | mHandlerThread.postTask(runnable)
122 | }
123 |
124 | override fun getItemCount(): Int {
125 | return calendarItemList.size
126 | }
127 |
128 | override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
129 | onBindViewHolder(
130 | holder = holder,
131 | position = position,
132 | calendarItem = calendarItemList[position]
133 | )
134 | }
135 |
136 | abstract fun onBindViewHolder(
137 | holder: RecyclerView.ViewHolder,
138 | position: Int,
139 | calendarItem: RecyclerCalenderViewItem
140 | )
141 |
142 | fun getItem(position: Int): RecyclerCalenderViewItem? {
143 | return if (position < calendarItemList.size) {
144 | calendarItemList[position];
145 | } else {
146 | null
147 | }
148 | }
149 |
150 | /**
151 | * Set LayoutManager of recycler view to GridLayoutManager with span of 7 (week)
152 | */
153 | override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
154 | super.onAttachedToRecyclerView(recyclerView)
155 |
156 | if (configuration.calenderViewType == RecyclerCalendarConfiguration.CalenderViewType.HORIZONTAL) {
157 | recyclerView.layoutManager = LinearLayoutManager(
158 | recyclerView.context,
159 | LinearLayoutManager.HORIZONTAL,
160 | false
161 | )
162 | } else {
163 | val gridLayoutManager =
164 | GridLayoutManager(recyclerView.context, 7)
165 | gridLayoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
166 | override fun getSpanSize(position: Int): Int {
167 | val spanSize: Int? = getItem(position)?.spanSize
168 | if (spanSize != null) {
169 | return spanSize
170 | }
171 | return 0
172 | }
173 | }
174 |
175 | recyclerView.layoutManager = gridLayoutManager
176 | }
177 | }
178 |
179 | override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
180 | super.onDetachedFromRecyclerView(recyclerView)
181 | mHandlerThread.quit()
182 | }
183 |
184 | // Thread handler
185 | class MyHandlerThread constructor(name: String) :
186 | HandlerThread(name) {
187 | private var handler: Handler? = null
188 | fun postTask(task: Runnable) {
189 | handler!!.post(task)
190 | }
191 |
192 | fun prepareHandler() {
193 | handler = Handler(looper)
194 | }
195 | }
196 | }
--------------------------------------------------------------------------------
/recyclercalendar/src/main/java/com/tejpratapsingh/recyclercalendar/adapter/SimpleRecyclerCalendarAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendar.adapter
2 |
3 | import android.content.Context
4 | import android.os.Build
5 | import android.util.TypedValue
6 | import android.view.LayoutInflater
7 | import android.view.MotionEvent
8 | import android.view.View
9 | import android.view.ViewGroup
10 | import android.widget.LinearLayout
11 | import android.widget.TextView
12 | import androidx.core.content.ContextCompat
13 | import androidx.recyclerview.widget.RecyclerView
14 | import com.tejpratapsingh.recyclercalendar.R
15 | import com.tejpratapsingh.recyclercalendar.model.RecyclerCalenderViewItem
16 | import com.tejpratapsingh.recyclercalendar.model.SimpleRecyclerCalendarConfiguration
17 | import com.tejpratapsingh.recyclercalendar.utilities.CalendarUtils
18 | import java.util.*
19 |
20 | class SimpleRecyclerCalendarAdapter(
21 | startDate: Date,
22 | endDate: Date,
23 | private val configuration: SimpleRecyclerCalendarConfiguration,
24 | private val dateSelectListener: OnDateSelected
25 | ) : RecyclerCalendarBaseAdapter(startDate, endDate, configuration) {
26 | interface OnDateSelected {
27 | fun onDateSelected(date: Date)
28 | }
29 |
30 | enum class POSITION {
31 | NONE, // Date is not part of Selection
32 | SINGLE, // Single Selected Date
33 | START, // Selection Start
34 | MIDDLE, // Selection Middle
35 | END // Selection End
36 | }
37 |
38 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
39 | val view: View = LayoutInflater.from(parent.context)
40 | .inflate(R.layout.item_simple_calendar, parent, false)
41 | return SimpleCalendarViewHolder(
42 | view
43 | )
44 | }
45 |
46 | override fun onBindViewHolder(
47 | holder: RecyclerView.ViewHolder,
48 | position: Int,
49 | calendarItem: RecyclerCalenderViewItem
50 | ) {
51 | val simpleViewHolder: SimpleCalendarViewHolder = holder as SimpleCalendarViewHolder
52 | val context: Context = simpleViewHolder.itemView.context
53 | simpleViewHolder.itemView.visibility = View.VISIBLE
54 |
55 | simpleViewHolder.itemView.setOnClickListener(null)
56 |
57 | highlightDate(simpleViewHolder, POSITION.NONE)
58 |
59 | simpleViewHolder.textViewDay.setTextColor(
60 | ContextCompat.getColor(
61 | context,
62 | R.color.colorBlack
63 | )
64 | )
65 | simpleViewHolder.textViewDate.setTextColor(
66 | ContextCompat.getColor(
67 | context,
68 | R.color.colorBlack
69 | )
70 | )
71 |
72 | simpleViewHolder.textViewDate.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14F)
73 | simpleViewHolder.textViewDate.setTextColor(ContextCompat.getColor(context, R.color.colorBlack))
74 |
75 | if (calendarItem.isHeader) {
76 | val selectedCalendar = Calendar.getInstance()
77 | selectedCalendar.time = calendarItem.date
78 |
79 | val month: String = CalendarUtils.dateStringFromFormat(
80 | locale = configuration.calendarLocale,
81 | date = selectedCalendar.time,
82 | format = CalendarUtils.DISPLAY_MONTH_FORMAT
83 | ) ?: ""
84 | val year = selectedCalendar[Calendar.YEAR].toLong()
85 |
86 | simpleViewHolder.textViewDay.text = year.toString()
87 | simpleViewHolder.textViewDate.setTextColor(ContextCompat.getColor(context, R.color.grey_500))
88 | simpleViewHolder.textViewDate.setTextSize(TypedValue.COMPLEX_UNIT_SP, 32F)
89 | simpleViewHolder.textViewDate.text = month
90 |
91 | simpleViewHolder.itemView.setOnClickListener(null)
92 |
93 | } else if (calendarItem.isEmpty) {
94 | simpleViewHolder.itemView.visibility = View.GONE
95 | simpleViewHolder.textViewDay.text = ""
96 | simpleViewHolder.textViewDate.text = ""
97 | } else {
98 | val calendarDate = Calendar.getInstance()
99 | calendarDate.time = calendarItem.date
100 |
101 | val currentDateString: String =
102 | CalendarUtils.dateStringFromFormat(
103 | locale = configuration.calendarLocale,
104 | date = calendarItem.date,
105 | format = CalendarUtils.DB_DATE_FORMAT
106 | )
107 | ?: ""
108 |
109 | val currentWeekDay: String = CalendarUtils.dateStringFromFormat(
110 | locale = configuration.calendarLocale,
111 | date = calendarDate.time,
112 | format = CalendarUtils.DISPLAY_WEEK_DAY_FORMAT
113 | ) ?: ""
114 |
115 | simpleViewHolder.textViewDay.text = currentWeekDay
116 |
117 | simpleViewHolder.textViewDate.text =
118 | CalendarUtils.dateStringFromFormat(
119 | locale = configuration.calendarLocale,
120 | date = calendarDate.time,
121 | format = CalendarUtils.DISPLAY_DATE_FORMAT
122 | ) ?: ""
123 |
124 | when (configuration.selectionMode) {
125 | is SimpleRecyclerCalendarConfiguration.SelectionModeSingle -> {
126 | val selectedDate: Date? =
127 | (configuration.selectionMode as SimpleRecyclerCalendarConfiguration.SelectionModeSingle).selectedDate
128 |
129 | if (selectedDate != null) {
130 | val stringSelectedTimeFormat: String =
131 | CalendarUtils.dateStringFromFormat(
132 | locale = configuration.calendarLocale,
133 | date = selectedDate,
134 | format = CalendarUtils.DB_DATE_FORMAT
135 | ) ?: ""
136 |
137 | if (currentDateString == stringSelectedTimeFormat) {
138 | highlightDate(simpleViewHolder, POSITION.SINGLE)
139 | }
140 |
141 | simpleViewHolder.itemView.setOnClickListener {
142 | (configuration.selectionMode as SimpleRecyclerCalendarConfiguration.SelectionModeSingle).selectedDate =
143 | calendarItem.date
144 | dateSelectListener.onDateSelected(calendarItem.date)
145 | notifyDataSetChanged()
146 | }
147 | }
148 | }
149 | is SimpleRecyclerCalendarConfiguration.SelectionModeMultiple -> {
150 | val selectionStartDateList: HashMap =
151 | (configuration.selectionMode as SimpleRecyclerCalendarConfiguration.SelectionModeMultiple).selectionStartDateList
152 |
153 | val calenderMultipleSelection: Calendar =
154 | Calendar.getInstance(configuration.calendarLocale)
155 | calenderMultipleSelection.time = calendarItem.date
156 | calenderMultipleSelection.add(Calendar.DATE, -1)
157 |
158 | val yesterdayDateString: String =
159 | CalendarUtils.dateStringFromFormat(
160 | locale = configuration.calendarLocale,
161 | date = calenderMultipleSelection.time,
162 | format = CalendarUtils.DB_DATE_FORMAT
163 | )
164 | ?: ""
165 |
166 | calenderMultipleSelection.add(Calendar.DATE, 2)
167 | val tomorrowDateString: String =
168 | CalendarUtils.dateStringFromFormat(
169 | locale = configuration.calendarLocale,
170 | date = calenderMultipleSelection.time,
171 | format = CalendarUtils.DB_DATE_FORMAT
172 | )
173 | ?: ""
174 |
175 | // Set Highlight background based on position of selected date
176 | if (selectionStartDateList[currentDateString] != null) {
177 | if (selectionStartDateList[yesterdayDateString] != null && selectionStartDateList[tomorrowDateString] != null) {
178 | highlightDate(simpleViewHolder, POSITION.MIDDLE)
179 | } else if (selectionStartDateList[yesterdayDateString] != null) {
180 | highlightDate(simpleViewHolder, POSITION.END)
181 | } else if (selectionStartDateList[tomorrowDateString] != null) {
182 | highlightDate(simpleViewHolder, POSITION.START)
183 | } else {
184 | highlightDate(simpleViewHolder, POSITION.SINGLE)
185 | }
186 | }
187 |
188 | simpleViewHolder.itemView.setOnClickListener {
189 | if (selectionStartDateList[currentDateString] == null) {
190 | selectionStartDateList[currentDateString] = calendarItem.date
191 | } else {
192 | selectionStartDateList.remove(currentDateString)
193 | }
194 | (configuration.selectionMode as SimpleRecyclerCalendarConfiguration.SelectionModeMultiple).selectionStartDateList =
195 | selectionStartDateList
196 | dateSelectListener.onDateSelected(calendarItem.date)
197 | notifyDataSetChanged()
198 | }
199 | }
200 | is SimpleRecyclerCalendarConfiguration.SelectionModeRange -> {
201 | val startDate: Date =
202 | (configuration.selectionMode as SimpleRecyclerCalendarConfiguration.SelectionModeRange).selectionStartDate
203 |
204 | val endDate: Date =
205 | (configuration.selectionMode as SimpleRecyclerCalendarConfiguration.SelectionModeRange).selectionEndDate
206 |
207 | val selectedDateInt: Int = currentDateString.toInt()
208 |
209 | val startDateInt: Int = (CalendarUtils.dateStringFromFormat(
210 | locale = configuration.calendarLocale,
211 | date = startDate,
212 | format = CalendarUtils.DB_DATE_FORMAT
213 | ) ?: Int.MAX_VALUE.toString()).toInt()
214 |
215 | val endDateInt: Int = (CalendarUtils.dateStringFromFormat(
216 | locale = configuration.calendarLocale,
217 | date = endDate,
218 | format = CalendarUtils.DB_DATE_FORMAT
219 | ) ?: Int.MIN_VALUE.toString()).toInt()
220 |
221 | if (selectedDateInt in startDateInt..endDateInt) {
222 | when (selectedDateInt) {
223 | startDateInt -> {
224 | highlightDate(simpleViewHolder, POSITION.START)
225 | }
226 | endDateInt -> {
227 | highlightDate(simpleViewHolder, POSITION.END)
228 | }
229 | else -> {
230 | highlightDate(simpleViewHolder, POSITION.MIDDLE)
231 | }
232 | }
233 | }
234 |
235 | simpleViewHolder.itemView.setOnClickListener {
236 | if (selectedDateInt < startDateInt) {
237 | (configuration.selectionMode as SimpleRecyclerCalendarConfiguration.SelectionModeRange).selectionStartDate =
238 | calendarItem.date
239 | } else if (selectedDateInt > endDateInt) {
240 | (configuration.selectionMode as SimpleRecyclerCalendarConfiguration.SelectionModeRange).selectionEndDate =
241 | calendarItem.date
242 | } else if (selectedDateInt in (startDateInt + 1) until endDateInt) {
243 | if (startDate.time - calendarItem.date.time > calendarItem.date.time - endDate.time) {
244 | // Selected date is closer to END date, so move end date
245 | (configuration.selectionMode as SimpleRecyclerCalendarConfiguration.SelectionModeRange).selectionStartDate =
246 | calendarItem.date
247 | } else {
248 | // Selected date is closer is START date, so move start date
249 | (configuration.selectionMode as SimpleRecyclerCalendarConfiguration.SelectionModeRange).selectionEndDate =
250 | calendarItem.date
251 | }
252 | }
253 | dateSelectListener.onDateSelected(calendarItem.date)
254 | notifyDataSetChanged()
255 | }
256 | }
257 | else -> {
258 | // Else None
259 | simpleViewHolder.itemView.setOnClickListener {
260 | dateSelectListener.onDateSelected(calendarItem.date)
261 | }
262 | }
263 | }
264 | }
265 | }
266 |
267 | class SimpleCalendarViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
268 |
269 | val layoutStartPadding: View =
270 | itemView.findViewById(R.id.layoutCalenderItemSimpleStartPadding)
271 | val layoutEndPadding: View = itemView.findViewById(R.id.layoutCalenderItemSimpleEndPadding)
272 | val layoutContainer: View =
273 | itemView.findViewById(R.id.layoutCalenderItemSimpleContainer)
274 | val layoutContainerInner: LinearLayout =
275 | itemView.findViewById(R.id.layoutCalenderItemSimpleContainerInner)
276 | val textViewDay: TextView = itemView.findViewById(R.id.textCalenderItemSimpleDay)
277 | val textViewDate: TextView = itemView.findViewById(R.id.textCalenderItemSimpleDate)
278 | }
279 |
280 | private fun highlightDate(monthViewHolder: SimpleCalendarViewHolder, position: POSITION) {
281 | val context: Context = monthViewHolder.itemView.context
282 |
283 | if (position == POSITION.START) {
284 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
285 | monthViewHolder.layoutContainer.background =
286 | ContextCompat.getDrawable(
287 | context,
288 | R.drawable.layout_round_corner_middle_filled
289 | )
290 |
291 | monthViewHolder.layoutContainerInner.background =
292 | ContextCompat.getDrawable(
293 | context,
294 | R.drawable.layout_round_corner_filled
295 | )
296 | } else {
297 | monthViewHolder.layoutContainer.setBackgroundDrawable(
298 | ContextCompat.getDrawable(
299 | context,
300 | R.drawable.layout_round_corner_middle_filled
301 | )
302 | )
303 |
304 | monthViewHolder.layoutContainerInner.setBackgroundDrawable(
305 | ContextCompat.getDrawable(
306 | context,
307 | R.drawable.layout_round_corner_filled
308 | )
309 | )
310 | }
311 |
312 | monthViewHolder.layoutStartPadding.visibility = View.VISIBLE
313 | monthViewHolder.layoutEndPadding.visibility = View.GONE
314 | } else if (position == POSITION.END) {
315 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
316 | monthViewHolder.layoutContainer.background =
317 | ContextCompat.getDrawable(
318 | context,
319 | R.drawable.layout_round_corner_middle_filled
320 | )
321 | monthViewHolder.layoutContainerInner.background =
322 | ContextCompat.getDrawable(
323 | context,
324 | R.drawable.layout_round_corner_filled
325 | )
326 | } else {
327 | monthViewHolder.layoutContainer.setBackgroundDrawable(
328 | ContextCompat.getDrawable(
329 | context,
330 | R.drawable.layout_round_corner_middle_filled
331 | )
332 | )
333 |
334 | monthViewHolder.layoutContainerInner.setBackgroundDrawable(
335 | ContextCompat.getDrawable(
336 | context,
337 | R.drawable.layout_round_corner_filled
338 | )
339 | )
340 | }
341 |
342 | monthViewHolder.layoutStartPadding.visibility = View.GONE
343 | monthViewHolder.layoutEndPadding.visibility = View.VISIBLE
344 | } else if (position == POSITION.MIDDLE) {
345 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
346 | monthViewHolder.layoutContainer.background =
347 | ContextCompat.getDrawable(
348 | context,
349 | R.drawable.layout_round_corner_middle_filled
350 | )
351 | monthViewHolder.layoutContainerInner.background = null
352 | } else {
353 | monthViewHolder.layoutContainer.setBackgroundDrawable(
354 | ContextCompat.getDrawable(
355 | context,
356 | R.drawable.layout_round_corner_middle_filled
357 | )
358 | )
359 | monthViewHolder.layoutContainerInner.setBackgroundDrawable(null)
360 | }
361 |
362 | monthViewHolder.layoutStartPadding.visibility = View.GONE
363 | monthViewHolder.layoutEndPadding.visibility = View.GONE
364 | } else if (position == POSITION.SINGLE) {
365 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
366 | monthViewHolder.layoutContainer.background = null
367 | monthViewHolder.layoutContainerInner.background =
368 | ContextCompat.getDrawable(
369 | context,
370 | R.drawable.layout_round_corner_filled
371 | )
372 | } else {
373 | monthViewHolder.layoutContainer.setBackgroundDrawable(null)
374 | monthViewHolder.layoutContainerInner.setBackgroundDrawable(
375 | ContextCompat.getDrawable(
376 | context,
377 | R.drawable.layout_round_corner_filled
378 | )
379 | )
380 | }
381 |
382 | monthViewHolder.layoutStartPadding.visibility = View.GONE
383 | monthViewHolder.layoutEndPadding.visibility = View.GONE
384 | } else if (position == POSITION.NONE) {
385 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
386 | monthViewHolder.layoutContainer.background = null
387 | monthViewHolder.layoutContainerInner.background = null
388 | } else {
389 | monthViewHolder.layoutContainer.setBackgroundDrawable(null)
390 | monthViewHolder.layoutContainerInner.setBackgroundDrawable(null)
391 | }
392 |
393 | monthViewHolder.layoutStartPadding.visibility = View.GONE
394 | monthViewHolder.layoutEndPadding.visibility = View.GONE
395 | }
396 |
397 | monthViewHolder.textViewDay.setTextColor(
398 | ContextCompat.getColor(
399 | context,
400 | R.color.colorWhite
401 | )
402 | )
403 | monthViewHolder.textViewDate.setTextColor(
404 | ContextCompat.getColor(
405 | context,
406 | R.color.colorWhite
407 | )
408 | )
409 | }
410 | }
--------------------------------------------------------------------------------
/recyclercalendar/src/main/java/com/tejpratapsingh/recyclercalendar/model/InfiniteRecyclerCalendarConfiguration.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendar.model
2 |
3 | import java.util.*
4 | import kotlin.collections.HashMap
5 |
6 | class InfiniteRecyclerCalendarConfiguration(
7 | calenderViewType: CalenderViewType,
8 | calendarLocale: Locale,
9 | includeMonthHeader: Boolean,
10 | selectionMode: SelectionMode
11 | ) : RecyclerCalendarConfiguration(
12 | calenderViewType, calendarLocale, includeMonthHeader
13 | ) {
14 | var selectionMode: SelectionMode = SelectionModeNone()
15 |
16 | init {
17 | this.selectionMode = selectionMode
18 | }
19 |
20 | open class SelectionMode {
21 | enum class TYPE {
22 | NONE
23 | }
24 |
25 | var selectionType: TYPE = TYPE.NONE
26 | }
27 |
28 | class SelectionModeNone : SelectionMode() {
29 | init {
30 | this.selectionType = TYPE.NONE
31 | }
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/recyclercalendar/src/main/java/com/tejpratapsingh/recyclercalendar/model/RecyclerCalendarConfiguration.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendar.model
2 |
3 | import java.util.*
4 |
5 | open class RecyclerCalendarConfiguration(
6 | val calenderViewType: CalenderViewType,
7 | val calendarLocale: Locale,
8 | val includeMonthHeader: Boolean
9 | ) {
10 | enum class CalenderViewType {
11 | HORIZONTAL, VERTICAL
12 | }
13 |
14 | enum class START_DAY_OF_WEEK(val offset: Int) {
15 | SATURDAY(1), SUNDAY(0), MONDAY(-1)
16 | }
17 |
18 | var weekStartOffset: START_DAY_OF_WEEK = START_DAY_OF_WEEK.SUNDAY
19 | }
--------------------------------------------------------------------------------
/recyclercalendar/src/main/java/com/tejpratapsingh/recyclercalendar/model/RecyclerCalenderViewItem.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendar.model
2 |
3 | import com.tejpratapsingh.recyclercalendar.utilities.CalendarUtils
4 | import java.util.*
5 |
6 | class RecyclerCalenderViewItem constructor(
7 | // date of calender item
8 | var date: Date,
9 | // Span size of cell for grid view
10 | // Month Header has span size of 7 (full week)
11 | // For offset for new month, we use empty cell which can have span from 0-6
12 | var spanSize: Int,
13 | // For offset of new month
14 | var isEmpty: Boolean,
15 | // Header is simply a Month name cell
16 | var isHeader: Boolean
17 | ) {
18 | override fun toString(): String {
19 | return String.format(
20 | Locale.getDefault(),
21 | "date: %s, spanSize: %d, isEmpty: %s, isHeader: %s",
22 | CalendarUtils.getGmt(date),
23 | spanSize,
24 | isEmpty.toString(),
25 | isHeader.toString()
26 | )
27 | }
28 | }
--------------------------------------------------------------------------------
/recyclercalendar/src/main/java/com/tejpratapsingh/recyclercalendar/model/SimpleRecyclerCalendarConfiguration.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendar.model
2 |
3 | import java.util.*
4 | import kotlin.collections.HashMap
5 |
6 | class SimpleRecyclerCalendarConfiguration(
7 | calenderViewType: CalenderViewType,
8 | calendarLocale: Locale,
9 | includeMonthHeader: Boolean,
10 | selectionMode: SelectionMode
11 | ) : RecyclerCalendarConfiguration(
12 | calenderViewType, calendarLocale, includeMonthHeader
13 | ) {
14 | var selectionMode: SelectionMode = SelectionModeNone()
15 | init {
16 | this.selectionMode = selectionMode
17 | }
18 |
19 | open class SelectionMode {
20 | enum class TYPE {
21 | NONE, SINGLE, MULTIPLE, RANGE
22 | }
23 |
24 | var selectionType: TYPE = TYPE.NONE
25 | }
26 |
27 | class SelectionModeNone : SelectionMode() {
28 | init {
29 | this.selectionType = TYPE.NONE
30 | }
31 | }
32 |
33 | class SelectionModeSingle(selectedDate: Date?) : SelectionMode() {
34 | var selectedDate: Date? = Date()
35 |
36 | init {
37 | this.selectionType = TYPE.SINGLE
38 | this.selectedDate = selectedDate
39 | }
40 | }
41 |
42 | class SelectionModeMultiple(selectionStartDateList: HashMap) : SelectionMode() {
43 | var selectionStartDateList: HashMap = HashMap()
44 |
45 | init {
46 | this.selectionType = TYPE.MULTIPLE
47 | this.selectionStartDateList = selectionStartDateList
48 | }
49 | }
50 |
51 | class SelectionModeRange(selectionStartDate: Date, selectionEndDate: Date) : SelectionMode() {
52 | var selectionStartDate: Date = Date()
53 | var selectionEndDate: Date = Date()
54 |
55 | init {
56 | this.selectionType = TYPE.RANGE
57 | this.selectionStartDate = selectionStartDate
58 | this.selectionEndDate = selectionEndDate
59 | }
60 | }
61 |
62 | }
--------------------------------------------------------------------------------
/recyclercalendar/src/main/java/com/tejpratapsingh/recyclercalendar/utilities/CalendarUtils.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendar.utilities
2 |
3 | import java.text.ParseException
4 | import java.text.SimpleDateFormat
5 | import java.util.*
6 |
7 | class CalendarUtils {
8 |
9 | companion object {
10 | @JvmStatic
11 | val DB_DATE_FORMAT = "yyyyMMdd"
12 | @JvmStatic
13 | val DB_YEAR_MONTH_FORMAT = "yyyyMM"
14 | @JvmStatic
15 | val DB_DATE_FORMAT_WITH_TIME = "yyyyMMddHHmm"
16 | @JvmStatic
17 | val SHORT_DATE_FORMAT = "dd-MMM-yyyy"
18 | @JvmStatic
19 | val LONG_DATE_FORMAT = "EEE, dd MMM yyyy"
20 | @JvmStatic
21 | val LONG_DATE_DAY = "E"
22 | @JvmStatic
23 | val DISPLAY_TIME_FORMAT = "hh:mm aaa"
24 | @JvmStatic
25 | val DISPLAY_DATE_TIME_FORMAT = "EEE, dd MMM yyyy, hh:mm aaa"
26 | @JvmStatic
27 | val DISPLAY_WEEK_DAY_FORMAT = "EEEEEE"
28 | @JvmStatic
29 | val DISPLAY_MONTH_FORMAT = "MMMM"
30 | @JvmStatic
31 | val DISPLAY_DATE_FORMAT = "dd"
32 |
33 | /**
34 | * Returns Date Object from date string and date format
35 | *
36 | * @param locale your preferred locale
37 | * @param date string date
38 | * @param format string date format
39 | * @return IF OK date object ELSE null
40 | */
41 | @JvmStatic
42 | fun dateFromAnyFormat(locale: Locale, date: String, format: String): Date? {
43 | return try {
44 | val formatter = SimpleDateFormat(format, locale)
45 | formatter.parse(date)
46 | } catch (e: ParseException) {
47 | e.printStackTrace()
48 | null
49 | }
50 | }
51 |
52 | /**
53 | * Returns Date Object from date string and date format
54 | *
55 | * @param locale your preferred locale
56 | * @param date string date
57 | * @param format string date format
58 | * @return IF OK date object ELSE null
59 | */
60 | @JvmStatic
61 | fun dateStringFromFormat(locale: Locale = Locale.getDefault(), date: Date, format: String): String? {
62 | return try {
63 | val formatter =
64 | SimpleDateFormat(format, locale)
65 | formatter.format(date)
66 | } catch (e: Exception) {
67 | e.printStackTrace()
68 | null
69 | }
70 | }
71 |
72 | /**
73 | * @param date date to be converted
74 | * @return String of date
75 | */
76 | @JvmStatic
77 | fun getGmt(date: Date): String {
78 | val dfDate = SimpleDateFormat("dd/MMM/yyyy HH:mm:ss", Locale.getDefault())
79 | return dfDate.format(date.time)
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/recyclercalendar/src/main/java/com/tejpratapsingh/recyclercalendar/views/InfiniteRecyclerCalendarView.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendar.views
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import androidx.recyclerview.widget.RecyclerView
6 | import com.tejpratapsingh.recyclercalendar.adapter.InfiniteRecyclerCalenderAdapter
7 | import com.tejpratapsingh.recyclercalendar.model.InfiniteRecyclerCalendarConfiguration
8 |
9 | class InfiniteRecyclerCalendarView : RecyclerView {
10 |
11 | constructor(context: Context) : super(context)
12 |
13 | constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
14 |
15 | constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
16 | context,
17 | attrs,
18 | defStyleAttr
19 | )
20 |
21 | fun initialise(
22 | configuration: InfiniteRecyclerCalendarConfiguration,
23 | dateSelectListener: InfiniteRecyclerCalenderAdapter.OnDateSelected
24 | ) {
25 | this.setItemViewCacheSize(10)
26 | this.setHasFixedSize(true)
27 |
28 | val infiniteRecyclerCalendarAdapter: InfiniteRecyclerCalenderAdapter =
29 | InfiniteRecyclerCalenderAdapter(
30 | configuration = configuration,
31 | dateSelectListener = dateSelectListener
32 | )
33 |
34 | adapter = infiniteRecyclerCalendarAdapter
35 |
36 | scrollToPosition(Int.MAX_VALUE / 2)
37 | }
38 | }
--------------------------------------------------------------------------------
/recyclercalendar/src/main/java/com/tejpratapsingh/recyclercalendar/views/SimpleRecyclerCalendarView.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendar.views
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import androidx.recyclerview.widget.RecyclerView
6 | import com.tejpratapsingh.recyclercalendar.adapter.SimpleRecyclerCalendarAdapter
7 | import com.tejpratapsingh.recyclercalendar.model.SimpleRecyclerCalendarConfiguration
8 | import java.util.*
9 |
10 | class SimpleRecyclerCalendarView : RecyclerView {
11 |
12 | private var configuration: SimpleRecyclerCalendarConfiguration? = null
13 |
14 | constructor(context: Context) : super(context)
15 |
16 | constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
17 |
18 | constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
19 | context,
20 | attrs,
21 | defStyleAttr
22 | )
23 |
24 | fun initialise(
25 | startDate: Date,
26 | endDate: Date,
27 | configuration: SimpleRecyclerCalendarConfiguration,
28 | dateSelectListener: SimpleRecyclerCalendarAdapter.OnDateSelected
29 | ) {
30 | this.configuration = configuration
31 |
32 | val simpleRecyclerCalendarView: SimpleRecyclerCalendarAdapter =
33 | SimpleRecyclerCalendarAdapter(
34 | startDate = startDate,
35 | endDate = endDate,
36 | configuration = configuration,
37 | dateSelectListener = dateSelectListener
38 | )
39 |
40 | adapter = simpleRecyclerCalendarView
41 | }
42 |
43 | fun getConfiguration(): SimpleRecyclerCalendarConfiguration? {
44 | return configuration
45 | }
46 | }
--------------------------------------------------------------------------------
/recyclercalendar/src/main/res/drawable-v21/layout_round_corner_filled.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | -
5 |
6 |
7 |
10 |
11 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/recyclercalendar/src/main/res/drawable-v21/layout_round_corner_left_filled.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | -
5 |
6 |
7 |
10 |
15 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/recyclercalendar/src/main/res/drawable-v21/layout_round_corner_middle_filled.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | -
5 |
6 |
7 |
10 |
11 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/recyclercalendar/src/main/res/drawable-v21/layout_round_corner_right_filled.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | -
5 |
6 |
7 |
10 |
15 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/recyclercalendar/src/main/res/drawable/layout_round_corner_filled.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
13 |
--------------------------------------------------------------------------------
/recyclercalendar/src/main/res/drawable/layout_round_corner_left_filled.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
12 |
17 |
--------------------------------------------------------------------------------
/recyclercalendar/src/main/res/drawable/layout_round_corner_middle_filled.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
13 |
--------------------------------------------------------------------------------
/recyclercalendar/src/main/res/drawable/layout_round_corner_right_filled.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
12 |
17 |
--------------------------------------------------------------------------------
/recyclercalendar/src/main/res/layout/item_infinite_calendar.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/recyclercalendar/src/main/res/layout/item_simple_calendar.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
18 |
19 |
25 |
26 |
31 |
32 |
33 |
34 |
42 |
43 |
52 |
53 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/recyclercalendar/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 | #000000
5 |
6 |
7 | #FFEBEE
8 | #FFCDD2
9 | #EF9A9A
10 | #E57373
11 | #EF5350
12 | #F44336
13 | #E53935
14 | #D32F2F
15 | #C62828
16 | #B71C1C
17 | #FF8A80
18 | #FF5252
19 | #FF1744
20 | #D50000
21 |
22 | #EDE7F6
23 | #D1C4E9
24 | #B39DDB
25 | #9575CD
26 | #7E57C2
27 | #673AB7
28 | #5E35B1
29 | #512DA8
30 | #4527A0
31 | #311B92
32 | #B388FF
33 | #7C4DFF
34 | #651FFF
35 | #6200EA
36 |
37 | #E1F5FE
38 | #B3E5FC
39 | #81D4FA
40 | #4FC3F7
41 | #29B6F6
42 | #03A9F4
43 | #039BE5
44 | #0288D1
45 | #0277BD
46 | #01579B
47 | #80D8FF
48 | #40C4FF
49 | #00B0FF
50 | #0091EA
51 |
52 | #E8F5E9
53 | #C8E6C9
54 | #A5D6A7
55 | #81C784
56 | #66BB6A
57 | #4CAF50
58 | #43A047
59 | #388E3C
60 | #2E7D32
61 | #1B5E20
62 | #B9F6CA
63 | #69F0AE
64 | #00E676
65 | #00C853
66 |
67 | #FFFDE7
68 | #FFF9C4
69 | #FFF59D
70 | #FFF176
71 | #FFEE58
72 | #FFEB3B
73 | #FDD835
74 | #FBC02D
75 | #F9A825
76 | #F57F17
77 | #FFFF8D
78 | #FFFF00
79 | #FFEA00
80 | #FFD600
81 |
82 | #FBE9E7
83 | #FFCCBC
84 | #FFAB91
85 | #FF8A65
86 | #FF7043
87 | #FF5722
88 | #F4511E
89 | #E64A19
90 | #D84315
91 | #BF360C
92 | #FF9E80
93 | #FF6E40
94 | #FF3D00
95 | #DD2C00
96 |
97 | #ECEFF1
98 | #CFD8DC
99 | #B0BEC5
100 | #90A4AE
101 | #78909C
102 | #607D8B
103 | #546E7A
104 | #455A64
105 | #37474F
106 | #263238
107 |
108 | #FCE4EC
109 | #F8BBD0
110 | #F48FB1
111 | #F06292
112 | #EC407A
113 | #E91E63
114 | #D81B60
115 | #C2185B
116 | #AD1457
117 | #880E4F
118 | #FF80AB
119 | #FF4081
120 | #F50057
121 | #C51162
122 |
123 | #E8EAF6
124 | #C5CAE9
125 | #9FA8DA
126 | #7986CB
127 | #5C6BC0
128 | #3F51B5
129 | #3949AB
130 | #303F9F
131 | #283593
132 | #1A237E
133 | #8C9EFF
134 | #536DFE
135 | #3D5AFE
136 | #304FFE
137 |
138 | #E0F7FA
139 | #B2EBF2
140 | #80DEEA
141 | #4DD0E1
142 | #26C6DA
143 | #00BCD4
144 | #00ACC1
145 | #0097A7
146 | #00838F
147 | #006064
148 | #84FFFF
149 | #18FFFF
150 | #00E5FF
151 | #00B8D4
152 |
153 | #F1F8E9
154 | #DCEDC8
155 | #C5E1A5
156 | #AED581
157 | #9CCC65
158 | #8BC34A
159 | #7CB342
160 | #689F38
161 | #558B2F
162 | #33691E
163 | #CCFF90
164 | #B2FF59
165 | #76FF03
166 | #64DD17
167 |
168 | #FFF8E1
169 | #FFECB3
170 | #FFE082
171 | #FFD54F
172 | #FFCA28
173 | #FFC107
174 | #FFB300
175 | #FFA000
176 | #FF8F00
177 | #FF6F00
178 | #FFE57F
179 | #FFD740
180 | #FFC400
181 | #FFAB00
182 |
183 | #EFEBE9
184 | #D7CCC8
185 | #BCAAA4
186 | #A1887F
187 | #8D6E63
188 | #795548
189 | #6D4C41
190 | #5D4037
191 | #4E342E
192 | #3E2723
193 |
194 | #F3E5F5
195 | #E1BEE7
196 | #CE93D8
197 | #BA68C8
198 | #AB47BC
199 | #9C27B0
200 | #8E24AA
201 | #7B1FA2
202 | #6A1B9A
203 | #4A148C
204 | #EA80FC
205 | #E040FB
206 | #D500F9
207 | #AA00FF
208 |
209 | #E3F2FD
210 | #BBDEFB
211 | #90CAF9
212 | #64B5F6
213 | #42A5F5
214 | #2196F3
215 | #1E88E5
216 | #1976D2
217 | #1565C0
218 | #0D47A1
219 | #82B1FF
220 | #448AFF
221 | #2979FF
222 | #2962FF
223 |
224 | #E0F2F1
225 | #B2DFDB
226 | #80CBC4
227 | #4DB6AC
228 | #26A69A
229 | #009688
230 | #00897B
231 | #00796B
232 | #00695C
233 | #004D40
234 | #A7FFEB
235 | #64FFDA
236 | #1DE9B6
237 | #00BFA5
238 |
239 | #F9FBE7
240 | #F0F4C3
241 | #E6EE9C
242 | #DCE775
243 | #D4E157
244 | #CDDC39
245 | #C0CA33
246 | #AFB42B
247 | #9E9D24
248 | #827717
249 | #F4FF81
250 | #EEFF41
251 | #C6FF00
252 | #AEEA00
253 |
254 | #FFF3E0
255 | #FFE0B2
256 | #FFCC80
257 | #FFB74D
258 | #FFA726
259 | #FF9800
260 | #FB8C00
261 | #F57C00
262 | #EF6C00
263 | #E65100
264 | #FFD180
265 | #FFAB40
266 | #FF9100
267 | #FF6D00
268 |
269 | #FAFAFA
270 | #F5F5F5
271 | #EEEEEE
272 | #E0E0E0
273 | #BDBDBD
274 | #9E9E9E
275 | #757575
276 | #616161
277 | #424242
278 | #212121
279 |
280 | #EF5350
281 | #EF5350
282 | #FF7043
283 | #8BC34A
284 | #F9A825
285 | #26C6DA
286 | #4285F4
287 | #42A5F5
288 | #5C6BC0
289 | #7E57C2
290 | #8D6E63
291 |
--------------------------------------------------------------------------------
/recyclercalendar/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 20sp
4 | 12sp
5 | 16sp
6 | 14sp
7 | 18sp
8 |
--------------------------------------------------------------------------------
/recyclercalendar/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Recycler Calendar
3 |
4 |
--------------------------------------------------------------------------------
/recyclercalendar/src/test/java/com/tejpratapsingh/recyclercalendar/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.tejpratapsingh.recyclercalendar
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(2, 2)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/sample_images/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/sample_images/.DS_Store
--------------------------------------------------------------------------------
/sample_images/backdrop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/sample_images/backdrop.png
--------------------------------------------------------------------------------
/sample_images/cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/sample_images/cover.png
--------------------------------------------------------------------------------
/sample_images/month_vertical.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/sample_images/month_vertical.gif
--------------------------------------------------------------------------------
/sample_images/month_vertical.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/sample_images/month_vertical.mp4
--------------------------------------------------------------------------------
/sample_images/progress_sample.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/sample_images/progress_sample.gif
--------------------------------------------------------------------------------
/sample_images/progress_sample.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/sample_images/progress_sample.mp4
--------------------------------------------------------------------------------
/sample_images/simplecalendar.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/sample_images/simplecalendar.jpeg
--------------------------------------------------------------------------------
/sample_images/simplecalendar_framed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/sample_images/simplecalendar_framed.png
--------------------------------------------------------------------------------
/sample_images/week_example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/sample_images/week_example.gif
--------------------------------------------------------------------------------
/sample_images/week_example.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tejpratap46/RecyclerCalendarAndroid/e35596e321244fa92bd4b1d61aff07c044d3fa17/sample_images/week_example.mp4
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':recyclercalendar'
2 | rootProject.name='RecyclerCalendarActivity'
3 |
--------------------------------------------------------------------------------