RepoPilotOpen in app →

prolificinteractive/material-calendarview

A Material design back port of Android's CalendarView

Healthy

Healthy across all four use cases

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • 17 active contributors
  • MIT licensed
  • CI configured
Show all 6 evidence items →
  • 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.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/prolificinteractive/material-calendarview)](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:

  1. 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.
  2. 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.
  3. 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 |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>prolificinteractive/material-calendarview</code></summary>
#!/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).

</details>

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)

  1. Create a new class implementing DayViewDecorator interface in library/src/main/java/com/prolificinteractive/materialcalendarview/ (library/src/main/java/com/prolificinteractive/materialcalendarview/DayViewDecorator.java)
  2. 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)
  3. 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)
  4. 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

  1. 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)
  2. Implement format(CalendarDay day) to return your custom String representation (library/src/main/java/com/prolificinteractive/materialcalendarview/format/DayFormatter.java)
  3. Set the formatter on MaterialCalendarView via setTitleFormatter() or setDayFormatter() (library/src/main/java/com/prolificinteractive/materialcalendarview/MaterialCalendarView.java)

Switch Between Month and Week Views

  1. Call setCalendarDisplayMode(CalendarMode.MONTHS) or setCalendarDisplayMode(CalendarMode.WEEKS) on MaterialCalendarView (library/src/main/java/com/prolificinteractive/materialcalendarview/MaterialCalendarView.java)
  2. The CalendarPager and CalendarPagerAdapter automatically swap between MonthView and WeekView rendering (library/src/main/java/com/prolificinteractive/materialcalendarview/CalendarPager.java)
  3. 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

  1. Set OnDateSelectedListener via setOnDateSelectedListener(MyListener) to receive callbacks when user taps a day (library/src/main/java/com/prolificinteractive/materialcalendarview/MaterialCalendarView.java)
  2. 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)
  3. 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
  • kizitonwose/CalendarView — Modern Kotlin/Jetpack alternative with similar features; comparison helps understand Material Calendar View's Java-legacy positioning
  • square/android-times-square — Earlier Android calendar library; Square's approach influenced Material Design calendar patterns
  • google/material-design-icons — Official Material Design icon set used for calendar UI elements and styling references
  • androidx/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

📝Recent commits

Click to expand
  • 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.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · prolificinteractive/material-calendarview — RepoPilot