segmented_ring_painter 1.1.3 copy "segmented_ring_painter: ^1.1.3" to clipboard
segmented_ring_painter: ^1.1.3 copied to clipboard

High-performance segmented circular progress and concentric activity ring widget for Flutter with gradient arcs, rounded caps, gap math, and tap hit-testing.

segmented_ring_painter #

Pub Version Pub Points Live Demo Pub Likes CI License


✨ Features #

  • πŸƒ Concentric Activity Rings (NestedActivityRings): Apple Fitness-style nested rings with authentic overlap drop-shadows on overachievement (>100% goal).
  • 🍰 Proportional & Segmented Rings (SegmentedRingChart): Dynamic multi-segment progress circles with precise angular gap spacing (perfect for Macro/Nutrition breakdowns, Budget allocation, or Multi-phase workflows).
  • 🎨 Rich Styling: Solid colors, sweep gradients, outer glow filters, and customizable end caps (RingCapStyle.round, butt, square).
  • πŸ‘† Built-in Touch Hit-Testing: Tap any individual segment or concentric ring to trigger tooltips, detail sheets, and selection states.
  • ⚑ Buttery Smooth: Hardware-accelerated CustomPainter with strict shouldRepaint dirty checks to ensure steady 60/120 FPS.
  • 🌐 All 6 Platforms Supported: 100% pure Dart & Flutter with zero native C/C++ dependencies. Works out-of-the-box on Android, iOS, Web, macOS, Windows, and Linux.

πŸ“¦ Installation #

Add segmented_ring_painter to your pubspec.yaml:

dependencies:
  segmented_ring_painter: ^1.1.2

Or run:

flutter pub add segmented_ring_painter

πŸš€ Quick Start #

1. Concentric Activity Rings (Apple Fitness Style) #

import 'package:flutter/material.dart';
import 'package:segmented_ring_painter/segmented_ring_painter.dart';

Widget buildActivityRings() {
  return NestedActivityRings(
    width: 220,
    height: 220,
    rings: [
      NestedRing(
        value: 520,
        maxValue: 500, // 104% -> Overachieved!
        color: const Color(0xFFFA114F),
        label: 'Move',
      ),
      NestedRing(
        value: 38,
        maxValue: 30,
        color: const Color(0xFFAAF724),
        label: 'Exercise',
      ),
      NestedRing(
        value: 9,
        maxValue: 12,
        color: const Color(0xFF00F5D4),
        label: 'Stand',
      ),
    ],
    style: const NestedRingsStyle(
      strokeWidth: 20.0,
      ringSpacing: 4.0,
      enableOverachievementShadow: true,
    ),
    center: const Icon(Icons.local_fire_department, color: Color(0xFFFA114F), size: 32),
    onRingTap: (index, ring) {
      print('Tapped ${ring.label}: ${ring.value}/${ring.maxValue}');
    },
  );
}

2. Segmented Proportional Ring (Nutrition / Budget) #

import 'package:flutter/material.dart';
import 'package:segmented_ring_painter/segmented_ring_painter.dart';

Widget buildMacroBreakdown() {
  return SegmentedRingChart(
    width: 220,
    height: 220,
    segments: [
      RingSegment(
        value: 180 * 4, // Carbs kcal
        color: const Color(0xFF38BDF8),
        label: 'Carbs',
        shadowColor: const Color(0xFF38BDF8),
        shadowBlur: 6.0,
      ),
      RingSegment(
        value: 140 * 4, // Protein kcal
        color: const Color(0xFF34D399),
        label: 'Protein',
        shadowColor: const Color(0xFF34D399),
        shadowBlur: 6.0,
      ),
      RingSegment(
        value: 65 * 9, // Fat kcal
        color: const Color(0xFFFBBF24),
        label: 'Fats',
        shadowColor: const Color(0xFFFBBF24),
        shadowBlur: 6.0,
      ),
    ],
    style: const SegmentedRingStyle(
      strokeWidth: 22.0,
      gapAngle: 5.0, // 5Β° angular gap between segments
      capStyle: RingCapStyle.round,
    ),
    center: const Text(
      '1,865\nkcal',
      textAlign: TextAlign.center,
      style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
    ),
    onSegmentTap: (index, segment) {
      print('Selected segment: ${segment.label} (${segment.value} kcal)');
    },
  );
}

πŸ› οΈ API Reference #

NestedActivityRings Properties #

Property Type Default Description
rings List<NestedRing> Required Concentric ring configurations from outer to inner.
style NestedRingsStyle NestedRingsStyle() Stroke thickness, spacing, shadows, and cap styling.
center Widget? null Optional widget anchored at the center of the innermost ring.
animationDuration Duration Duration(milliseconds: 1000) Duration for entrance & value change animations.
animationCurve Curve Curves.easeOutCubic Interpolation curve for smooth physics.
onRingTap Function(int, NestedRing)? null Callback returning the tapped ring index and data.

SegmentedRingChart Properties #

Property Type Default Description
segments List<RingSegment> Required The data segments to partition across the ring.
style SegmentedRingStyle SegmentedRingStyle() Stroke width, angular gap, background track, glow.
mode SegmentedRingMode SegmentedRingMode.proportional proportional (auto-sums to 100%) or absolute.
totalValue double? null Target total capacity for SegmentedRingMode.absolute.
center Widget? null Optional center widget.
onSegmentTap Function(int, RingSegment)? null Callback returning the tapped segment index and data.

πŸ’– Support the Project #

If you find this project useful, consider supporting its active maintenance and future development:

Buy Me A Coffee GitHub Sponsors Patreon


πŸ“„ License #

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

Maintained with ❀️ by Govind Tank.

2
likes
160
points
478
downloads

Documentation

API reference

Publisher

verified publishergovindtank.is-a.dev

Weekly Downloads

High-performance segmented circular progress and concentric activity ring widget for Flutter with gradient arcs, rounded caps, gap math, and tap hit-testing.

Repository (GitHub)
View/report issues

Topics

#chart #progress #activity-rings #fitness #custom-painter

License

Apache-2.0 (license)

Dependencies

flutter

More

Packages that depend on segmented_ring_painter