prolificinteractive/material-calendarview
A Material design back port of Android's CalendarView
Healthy across all four use cases
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓17 active contributors
- ✓MIT licensed
- ✓CI configured
Show all 6 evidence items →Show less
- ✓Tests present
- ⚠Stale — last commit 3y ago
- ⚠Concentrated ownership — top contributor handles 79% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/prolificinteractive/material-calendarview)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/prolificinteractive/material-calendarview on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: prolificinteractive/material-calendarview
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/prolificinteractive/material-calendarview shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- 17 active contributors
- MIT licensed
- CI configured
- Tests present
- ⚠ Stale — last commit 3y ago
- ⚠ Concentrated ownership — top contributor handles 79% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live prolificinteractive/material-calendarview
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/prolificinteractive/material-calendarview.
What it runs against: a local clone of prolificinteractive/material-calendarview — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in prolificinteractive/material-calendarview | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 1106 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of prolificinteractive/material-calendarview. If you don't
# have one yet, run these first:
#
# git clone https://github.com/prolificinteractive/material-calendarview.git
# cd material-calendarview
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of prolificinteractive/material-calendarview and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "prolificinteractive/material-calendarview(\\.git)?\\b" \\
&& ok "origin remote is prolificinteractive/material-calendarview" \\
|| miss "origin remote is not prolificinteractive/material-calendarview (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "library/src/main/java/com/prolificinteractive/materialcalendarview/MaterialCalendarView.java" \\
&& ok "library/src/main/java/com/prolificinteractive/materialcalendarview/MaterialCalendarView.java" \\
|| miss "missing critical file: library/src/main/java/com/prolificinteractive/materialcalendarview/MaterialCalendarView.java"
test -f "library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarPager.java" \\
&& ok "library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarPager.java" \\
|| miss "missing critical file: library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarPager.java"
test -f "library/src/main/java/com/prolificinteractive/materialcalendarview/MonthView.java" \\
&& ok "library/src/main/java/com/prolificinteractive/materialcalendarview/MonthView.java" \\
|| miss "missing critical file: library/src/main/java/com/prolificinteractive/materialcalendarview/MonthView.java"
test -f "library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarDay.java" \\
&& ok "library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarDay.java" \\
|| miss "missing critical file: library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarDay.java"
test -f "library/src/main/java/com/prolificinteractive/materialcalendarview/DayViewDecorator.java" \\
&& ok "library/src/main/java/com/prolificinteractive/materialcalendarview/DayViewDecorator.java" \\
|| miss "missing critical file: library/src/main/java/com/prolificinteractive/materialcalendarview/DayViewDecorator.java"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 1106 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~1076d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/prolificinteractive/material-calendarview"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Material Calendar View is a Material Design-compliant Android calendar widget that back-ports Google's CalendarView with a modern look-and-feel. It provides a customizable calendar UI supporting single/multiple date selection, date range filtering, week/month viewing modes, and day decoration/highlighting through the DayViewDecorator system. Single-module structure: /library/src/main/java/com/prolificinteractive/materialcalendarview/ contains the core widget and adapters. MaterialCalendarView.java is the main public API. Supporting architecture includes CalendarPager(Adapter|View) for view paging, MonthView/WeekView for display modes, DayView for individual day rendering, and DayViewDecorator for extensible decoration logic.
👥Who it's for
Android app developers building date selection UIs who need a production-ready Material Design calendar without building from scratch. Specifically used by developers who want to replace the platform CalendarView with something more visually polished and feature-rich.
🌱Maturity & risk
Actively maintained and production-ready. The repo shows a complete Gradle build setup with Travis CI integration (.travis.yml), comprehensive documentation in /docs/, JitPack distribution, and a structured library module. Last activity and issue response patterns indicate ongoing maintenance for a stable, well-used library.
Low risk for core functionality but moderate maintenance burden: single primary maintainer (prolificinteractive), Java-only codebase with no Kotlin migration, minimal test coverage visible in file listing, and Android version support tied to build-tools 3.3.0 (from 2019). Library dependencies are well-managed via dependencies.gradle, but older Gradle wrapper (5.1.1) may require updates for latest Android Studio compatibility.
Active areas of work
No specific recent changes visible in provided file list. Repository appears stable with documentation in /docs/ covering customization, decorators, and builder patterns. The presence of CHANGELOG.md suggests semantic versioning practices, but update frequency is not apparent from the provided snapshot.
🚀Get running
git clone https://github.com/prolificinteractive/material-calendarview.git
cd material-calendarview
./gradlew build
The gradlew wrapper script handles Gradle 5.1.1 automatically. Add the library as a JitPack dependency to your Android project via build.gradle.
Daily commands:
This is a library, not an app. Build with ./gradlew build or ./gradlew assembleDebug to generate the AAR. Include it in an Android app's build.gradle: implementation 'com.github.prolificinteractive:material-calendarview:${version}' (via JitPack). See /docs/ for XML layout and programmatic configuration examples.
🗺️Map of the codebase
library/src/main/java/com/prolificinteractive/materialcalendarview/MaterialCalendarView.java— Core public API and main entry point; all integrations depend on understanding this widget's configuration and lifecycle.library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarPager.java— Manages ViewPager navigation and month/week switching logic; critical for understanding calendar's scrolling and layout behavior.library/src/main/java/com/prolificinteractive/materialcalendarview/MonthView.java— Renders individual month grids; responsible for day layout, decorations, and touch handling in month mode.library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarDay.java— Immutable value object representing a single day; fundamental data model used throughout the codebase.library/src/main/java/com/prolificinteractive/materialcalendarview/DayViewDecorator.java— Extension point for visual customization; any decoration (colors, dots, styling) flows through this interface.library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarPagerAdapter.java— Adapter creating month/week views; controls which view type is displayed and how pagination works.
🛠️How to make changes
Add a Custom Day Decorator (Coloring, Dots, Styling)
- Create a new class implementing DayViewDecorator interface in library/src/main/java/com/prolificinteractive/materialcalendarview/ (
library/src/main/java/com/prolificinteractive/materialcalendarview/DayViewDecorator.java) - Implement getKey() to return a unique decorator ID and shouldDecorate(CalendarDay day) to return true for target days (
library/src/main/java/com/prolificinteractive/materialcalendarview/DayViewDecorator.java) - Implement decorate(DayViewFacade facade) to apply colors, drawables, or spans via facade methods (setBackgroundDrawable, setTextColor, addSpan) (
library/src/main/java/com/prolificinteractive/materialcalendarview/DayViewFacade.java) - Register the decorator on MaterialCalendarView via addDecorator(YourDecorator) in your Activity or Fragment (
library/src/main/java/com/prolificinteractive/materialcalendarview/MaterialCalendarView.java)
Add Custom Title or Day Formatting
- Create a new class implementing TitleFormatter or DayFormatter in library/src/main/java/com/prolificinteractive/materialcalendarview/format/ (
library/src/main/java/com/prolificinteractive/materialcalendarview/format/TitleFormatter.java) - Implement format(CalendarDay day) to return your custom String representation (
library/src/main/java/com/prolificinteractive/materialcalendarview/format/DayFormatter.java) - Set the formatter on MaterialCalendarView via setTitleFormatter() or setDayFormatter() (
library/src/main/java/com/prolificinteractive/materialcalendarview/MaterialCalendarView.java)
Switch Between Month and Week Views
- Call setCalendarDisplayMode(CalendarMode.MONTHS) or setCalendarDisplayMode(CalendarMode.WEEKS) on MaterialCalendarView (
library/src/main/java/com/prolificinteractive/materialcalendarview/MaterialCalendarView.java) - The CalendarPager and CalendarPagerAdapter automatically swap between MonthView and WeekView rendering (
library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarPager.java) - Optional: Listen for layout changes via OnMonthChangedListener or inspection of getSelectedDate() state (
library/src/main/java/com/prolificinteractive/materialcalendarview/OnMonthChangedListener.java)
Handle Date Selection and Validation
- Set OnDateSelectedListener via setOnDateSelectedListener(MyListener) to receive callbacks when user taps a day (
library/src/main/java/com/prolificinteractive/materialcalendarview/MaterialCalendarView.java) - Optionally restrict selectable dates by adding a DayViewDecorator that returns false from shouldDecorate() for disabled days, or use setMinimumDate()/setMaximumDate() (
library/src/main/java/com/prolificinteractive/materialcalendarview/MaterialCalendarView.java) - Programmatically get selected dates via getSelectedDate() or getSelectedDates() (if range mode supported) (
library/src/main/java/com/prolificinteractive/materialcalendarview/)
🪤Traps & gotchas
CalendarDay equality and hashing are relied upon for selection tracking—mutation or improper use will cause selection bugs. ViewPager-based navigation assumes a fixed range; DateRangeIndex.java enforces min/max bounds, but misconfiguring these causes crashes. DayViewFacade applies decorations at draw time, so modifying facade state outside the decorator callback has no effect. Locale handling in LocalUtils.java is tied to system Locale; custom first-day-of-week must be set explicitly or defaults to Locale default. No R.class generation visible—confirm Android support library versions in dependencies.gradle match your compile SDK.
💡Concepts to learn
- ViewPager Adapter Pattern — CalendarPagerAdapter and MonthPagerAdapter use ViewPager to efficiently page through months/weeks without recreating views; understanding this pattern is essential for modifying navigation
- Decorator Pattern (DayViewDecorator/DayViewFacade) — Core extensibility mechanism allowing custom day styling without modifying core view code; critical for understanding how features like highlighting or custom labels work
- Custom View Measurement & Layout — DayView, MonthView, and WeekView override onMeasure/onLayout to create responsive grids; understanding Android layout mechanics is required to modify dimensions or spacing
- Immutable Value Objects (CalendarDay) — CalendarDay uses immutability for safe use as HashMap keys in selection tracking; changes to this pattern can break date selection logic
- Material Design Color & Typography Systems — DayView rendering and MonthView styling rely on Material Design color tokens and type scales; customization requires familiarity with these constraints
- Locale-Aware Date Formatting — LocalUtils.java and WeekDayView depend on Locale for week-day names and calendar calculations; misconfiguration breaks internationalization
- Range Indexing (DateRangeIndex) — Efficiently maps arbitrary date ranges to ViewPager positions; misunderstanding this algorithm makes it impossible to implement custom date filtering or bounds checking
🔗Related repos
kizitonwose/CalendarView— Modern Kotlin/Jetpack alternative with similar features; comparison helps understand Material Calendar View's Java-legacy positioningsquare/android-times-square— Earlier Android calendar library; Square's approach influenced Material Design calendar patternsgoogle/material-design-icons— Official Material Design icon set used for calendar UI elements and styling referencesandroidx/androidx— AndroidX libraries (replace support-v7) that Material Calendar View targets; necessary for gradle dependency resolution
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add unit tests for DecoratorResult and DayViewFacade decorator system
The decorator pattern is a core feature of this library (evidenced by DayViewDecorator.java, DecoratorResult.java, and DayViewFacade.java), but there are no visible test files in the repository structure. This is critical for ensuring decorators work correctly across different states and edge cases. Adding comprehensive unit tests would prevent regressions and give contributors confidence when modifying the decorator system.
- [ ] Create library/src/test/java/com/prolificinteractive/materialcalendarview/ directory structure
- [ ] Write tests for DecoratorResult.java covering all decorator application scenarios
- [ ] Write tests for DayViewFacade.java covering setter chains and state management
- [ ] Write tests for DayViewDecorator.java interface implementations with mock decorators
- [ ] Run tests locally with ./gradlew test to validate
Add unit tests for CalendarDay and DateRangeIndex date logic
CalendarDay.java and DateRangeIndex.java handle core date manipulation and range calculations, which are error-prone without proper test coverage. Given this is a calendar library, bugs in date handling directly impact user experience. The absence of visible date logic tests makes this a high-priority gap.
- [ ] Create library/src/test/java/com/prolificinteractive/materialcalendarview/ test directory
- [ ] Write tests for CalendarDay.java covering leap years, month boundaries, and comparisons
- [ ] Write tests for DateRangeIndex.java covering range creation, iteration, and edge cases (e.g., single-day ranges)
- [ ] Add tests for LocalUtils.java locale-specific date formatting if applicable
- [ ] Run ./gradlew test to verify coverage
Migrate from Travis CI to GitHub Actions with comprehensive CI workflow
The repo uses .travis.yml (visible in file structure) which is outdated compared to GitHub Actions. The current setup only references Travis in badges but provides no visibility into what tests/checks run. A GitHub Actions workflow file would provide: build validation on multiple Android API levels, automated testing on PRs, and clearer contributor guidelines. This would modernize the project and reduce CI maintenance overhead.
- [ ] Create .github/workflows/android-build.yml with matrix builds for API levels 21, 28, 29, 30
- [ ] Add build steps: gradlew clean build, lint checks, and unit test execution
- [ ] Add Gradle cache action to speed up CI runs
- [ ] Update README.md to reference GitHub Actions badge instead of Travis
- [ ] Remove or deprecate .travis.yml with a comment directing to GitHub Actions
- [ ] Test workflow by pushing to a feature branch
🌿Good first issues
- Add unit tests for CalendarDay.java equality, hashing, and comparison logic; currently no test files visible in the repo.
- Document the DateRangeIndex.java algorithm with concrete examples in docs/—it's non-obvious how min/max date bounds interact with month indexing.
- Extend format/ package with a WeekDayFormatter implementation for locales that prefer 2-letter weekday abbreviations (e.g., 'Mo', 'Tu' instead of 'Mon', 'Tue').
⭐Top contributors
Click to expand
Top contributors
- @quentin41500 — 79 commits
- [@Brad Barnhill](https://github.com/Brad Barnhill) — 3 commits
- @tevjef — 2 commits
- @jorpaspr — 2 commits
- @codeskraps — 2 commits
📝Recent commits
Click to expand
Recent commits
04fae81— fix travis-ci build due to incorrect dependencies for building (Brad Barnhill)67b3e4e— update gradle plugin to 3.3.0, gradle 5.1.1, name artifact when AAR is built to prevent unnecessary file renaming (Brad Barnhill)578a1f7— Update threetenabp dependency to version 1.1.1 which fixes an issue compiling with AS3.3 and gradle plugin 3.3.0, bump l (Brad Barnhill)c8d2c77— Fix - Cleanup Arrow Attrs And Doc (quentin41500)3fe9162— Update CHANGELOG.md (quentin41500)8e439b7— Feature - RTL Support (#844) (quentin41500)7562372— Feature - Replace Header with XML Layout (#841) (quentin41500)5f39050— Feature - Vectors (#840) (quentin41500)7a5a045— Fix - Remove Restoration of XML parameters (#838) (quentin41500)bf1015c— Chore - README & CHANGELOG (quentin41500)
🔒Security observations
The codebase has moderate security concerns primarily related to outdated build tools and deprecated repository configurations. The main risks stem from using Android Gradle Plugin 3.3.0 (2019) and Gradle 5.1.1, which lack modern security patches and features. The deprecated jcenter() repository presents reliability and potential security supply-chain risks. The actual application code appears to be a UI library with limited attack surface (no obvious injection risks, network calls, or sensitive data handling visible in the file structure). Immediate action should be taken to modernize the build system and dependency management to mitigate these risks.
- High · Outdated Gradle Build Tools —
build.gradle, gradle/wrapper/gradle-wrapper.properties. The project uses Android Gradle Plugin version 3.3.0 and Gradle 5.1.1, both significantly outdated (released in 2019). These versions may contain known security vulnerabilities and lack security patches for dependency resolution, build process vulnerabilities, and Android framework issues. Fix: Update to the latest stable versions of Gradle (8.x) and Android Gradle Plugin (8.x). Run 'gradlew wrapper --gradle-version=8.x' to update safely. - Medium · Outdated Android Build Dependencies —
build.gradle (buildscript dependencies section). The android-maven-gradle-plugin version 2.1 is outdated and may lack security updates. Additionally, jcenter() repository is used which has been sunset by Bintray. Fix: Replace jcenter() with mavenCentral(). Update to android-maven-gradle-plugin:2.1 or consider switching to maven-publish plugin. Remove jcenter() from all repositories. - Medium · Deprecated Repository Configuration —
build.gradle (allprojects repositories section). The build configuration uses jcenter() repository which was sunset by Bintray in 2021. While google() and mavenCentral() are available alternatives, jcenter() should be removed to prevent build failures and ensure dependency availability. Fix: Remove jcenter() repository configuration. Use only google() and mavenCentral() for dependency resolution. Verify all dependencies are available in these repositories. - Low · Missing Security Properties in gradle.properties —
gradle.properties. The gradle.properties file is present but its content is not shown. This could be a location for potentially exposed secrets or sensitive build configurations. Fix: Review gradle.properties to ensure no credentials, API keys, or sensitive information are hardcoded. Use environment variables or gradle.properties with .gitignore exclusions for sensitive values. - Low · Unrestricted Network Repositories —
build.gradle (allprojects section, commented maven repository). The build configuration includes a commented-out SNAPSHOT repository reference (oss.sonatype.org) which suggests the project may use SNAPSHOT dependencies. SNAPSHOT versions are unstable and may contain untested code. Fix: Avoid using SNAPSHOT versions in production builds. If needed for development, isolate to a separate build configuration. Document any non-release dependencies used during development.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.