contribution_heatmap 0.2.0-dev.3
contribution_heatmap: ^0.2.0-dev.3 copied to clipboard
A high-performance, GitHub-like contribution heatmap calendar widget for Flutter. Built with a custom RenderBox for maximum efficiency and full customization.
Contribution Heatmap #
A high-performance, GitHub-like contribution heatmap widget for Flutter. This widget provides a visual representation of contribution data over time, similar to GitHub's contribution graph with proper i18n support and intelligent month separation.
[Contribution Heatmap with splittdMonthView] [Contribution Heatmap without splittdMonthView]
β¨ Features #
- π Ultra-High Performance: Custom RenderBox implementation with optimized rendering pipeline
- π Interactive: Full tap support with proper hit testing and gesture handling
- π¨ Fully Customizable: Colors, sizing, labels, and layout options
- π Split Month View: NEW! Visual month separation with intelligent empty cell insertion
- βΏ Accessibility Ready: Supports text scaling and high contrast modes
- π Internationalized: Locale-aware text rendering with customizable start weekdays
- πΎ Memory Efficient: Optimized data structures minimize memory usage and GC pressure
- π§ Smart Invalidation: Only recomputes what's needed, not on every frame
π Quick Start #
Basic Usage #
import 'package:flutter/material.dart';
import 'package:contribution_heatmap/contribution_heatmap.dart';
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ContributionHeatmap(
entries: [
ContributionEntry(DateTime(2025, 8, 15), 5),
ContributionEntry(DateTime(2025, 8, 16), 3),
ContributionEntry(DateTime(2025, 8, 17), 8),
// Add more entries...
],
onCellTap: (date, value) {
print('Tapped: $date with $value contributions');
},
);
}
}
Split Month View (NEW!) #
Enable clear visual separation between months with intelligent spacing:
ContributionHeatmap(
entries: myContributionData,
splittedMonthView: true, // NEW: Adds visual gaps between months
onCellTap: (date, value) {
print('Tapped: $date with $value contributions');
},
)
Split Month View Benefits:
- Smart Spacing: Only adds necessary empty cells, not full weeks
- Perfect Alignment: First month aligns with week start day
- Clean Boundaries: Clear visual separation between consecutive months
Advanced Usage #
ContributionHeatmap(
entries: myContributionData,
// Custom date range
minDate: DateTime(2025, 1, 1),
maxDate: DateTime.now(),
splittedMonthView: true, // NEW: Enable split month view
// Visual customization
cellSize: 14.0,
cellSpacing: 4.0,
cellRadius: 3.0,
padding: EdgeInsets.all(20),
// Custom color scale
colorScale: (value) {
if (value == 0) return Colors.grey[100]!;
if (value <= 2) return Colors.green[200]!;
if (value <= 5) return Colors.green[400]!;
return Colors.green[600]!;
},
// Custom text styles
monthTextStyle: TextStyle(
color: Colors.grey[600],
fontSize: 12,
fontWeight: FontWeight.w500,
),
weekdayTextStyle: TextStyle(
color: Colors.grey[500],
fontSize: 11,
),
// Week starts on Sunday (US style)
startWeekday: DateTime.sunday,
// Handle cell interactions
onCellTap: (date, value) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('${date.toIso8601String().split('T')[0]}'),
content: Text('$value contributions on this date'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('Close'),
),
],
),
);
},
)
π Data Model #
ContributionEntry #
The Data structure for contribution data:
class ContributionEntry {
final DateTime date; // Day-level precision
final int count; // Number of contributions (>= 0)
const ContributionEntry(this.date, this.count);
}
π i18n Support #
Currently, this package supports English (EN) and
- π«π· French (fr-FR)
- π©πͺ German (de-DE)
- πͺπΈ Spanish (es-ES)
More languages will be added soon.
Exemple de Contribution Heatmap en franΓ§ais (fr-FR) [Exemple de Contribution Heatmap en franΓ§ais (fr-FR)]
π¨ Customization Options #
Visual Properties #
| Property | Type | Default | Description |
|---|---|---|---|
cellSize |
double |
12.0 |
Size of each contribution cell |
cellSpacing |
double |
3.0 |
Spacing between cells |
cellRadius |
double |
2.0 |
Corner radius for rounded cells |
padding |
EdgeInsets |
EdgeInsets.all(16) |
Outer padding around widget |
Labels & Text #
| Property | Type | Default | Description |
|---|---|---|---|
showMonthLabels |
bool |
true |
Show month names above the heatmap |
showWeekdayLabels |
bool |
true |
Show day names on the left |
monthTextStyle |
TextStyle? |
null |
Custom style for month labels |
weekdayTextStyle |
TextStyle? |
null |
Custom style for weekday labels |
Date & Layout #
| Property | Type | Default | Description |
|---|---|---|---|
minDate |
DateTime? |
null |
Override minimum date (auto-calculated if null) |
maxDate |
DateTime? |
null |
Override maximum date (auto-calculated if null) |
startWeekday |
int |
DateTime.monday |
First day of week (1=Mon, 7=Sun) |
splittedMonthView |
bool |
false |
NEW! Enable visual month separation |
Colors & Interaction #
| Property | Type | Default | Description |
|---|---|---|---|
colorScale |
Color Function(int)? |
null |
Custom color mapping function |
onCellTap |
void Function(DateTime, int)? |
null |
Callback for cell tap events |
β‘ Performance Characteristics #
Rendering Performance #
- O(1) cell value lookups during painting
- Custom RenderBox implementation bypasses widget rebuilds
- Smart invalidation - only recomputes when properties actually change
- Efficient hit testing with proper bounds checking
- Optimized split month rendering with minimal computational overhead
Memory Efficiency #
- HashMap-based data structure for fast lookups
- Minimal object allocation during painting
- Proper gesture recognizer cleanup prevents memory leaks
- Optimized text rendering with cached TextPainter objects
- Linear date sequence for efficient split month calculations
Scalability #
- Handles thousands of data points efficiently
- Constant time complexity for cell rendering
- Responsive layout adapts to available space
- Smooth interactions even with large datasets and split months
π Contributing #
Feel free to contribute! Check out the guides for more information.