linear_progress_bar 3.0.0
linear_progress_bar: ^3.0.0 copied to clipboard
A powerful and customizable progress indicator library for Flutter. Supports linear bars, circular percent indicators, gauges, dots indicators, titled progress, gradients, and animations.
import 'package:flutter/material.dart';
import 'package:linear_progress_bar/linear_progress_bar.dart';
void main() {
runApp(const MyApp());
}
/// The main application widget.
class MyApp extends StatelessWidget {
/// Creates the main application widget.
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Linear Progress Bar',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const ExamplesPage(),
);
}
}
/// The main examples page that displays different progress bar examples.
class ExamplesPage extends StatefulWidget {
/// Creates the examples page widget.
const ExamplesPage({super.key});
@override
State<ExamplesPage> createState() => _ExamplesPageState();
}
class _ExamplesPageState extends State<ExamplesPage> {
int _selectedIndex = 0;
final List<Widget> _pages = const [
LinearProgressExamples(),
DotsProgressExamples(),
TitledProgressExamples(),
CircularPercentExamples(),
GaugeExamples(),
LinearGaugeExamples(),
RadialGaugeExamples(),
LinearPercentExamples(),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text('Progress Indicators Demo'),
),
body: _pages[_selectedIndex],
bottomNavigationBar: NavigationBar(
selectedIndex: _selectedIndex,
onDestinationSelected: (index) {
setState(() => _selectedIndex = index);
},
destinations: const [
NavigationDestination(
icon: Icon(Icons.linear_scale),
label: 'Linear',
),
NavigationDestination(
icon: Icon(Icons.more_horiz),
label: 'Dots',
),
NavigationDestination(
icon: Icon(Icons.title),
label: 'Titled',
),
NavigationDestination(
icon: Icon(Icons.circle_outlined),
label: 'Circular',
),
NavigationDestination(
icon: Icon(Icons.speed),
label: 'Gauge',
),
NavigationDestination(
icon: Icon(Icons.straighten),
label: 'L-Gauge',
),
NavigationDestination(
icon: Icon(Icons.radar),
label: 'R-Gauge',
),
NavigationDestination(
icon: Icon(Icons.percent),
label: 'Percent',
),
],
),
);
}
}
/// Examples of linear progress bars
class LinearProgressExamples extends StatefulWidget {
/// Creates the linear progress examples widget.
const LinearProgressExamples({super.key});
@override
State<LinearProgressExamples> createState() => _LinearProgressExamplesState();
}
class _LinearProgressExamplesState extends State<LinearProgressExamples> {
int _currentStep = 3;
final int _maxSteps = 6;
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildSectionTitle('Basic Linear Progress'),
_buildExampleCard(
'Simple Progress Bar',
LinearProgressBar(
maxSteps: _maxSteps,
progressType: ProgressType.linear,
currentStep: _currentStep,
progressColor: Colors.blue,
backgroundColor: Colors.grey.shade300,
minHeight: 10,
),
),
_buildSectionTitle('Rounded Corners'),
_buildExampleCard(
'With Border Radius',
LinearProgressBar(
maxSteps: _maxSteps,
progressType: ProgressType.linear,
currentStep: _currentStep,
progressColor: Colors.green,
backgroundColor: Colors.grey.shade300,
borderRadius: BorderRadius.circular(10),
minHeight: 16,
),
),
_buildSectionTitle('Different Heights'),
_buildExampleCard(
'Thin (4px)',
LinearProgressBar(
maxSteps: _maxSteps,
progressType: ProgressType.linear,
currentStep: _currentStep,
progressColor: Colors.purple,
backgroundColor: Colors.grey.shade300,
minHeight: 4,
borderRadius: BorderRadius.circular(2),
),
),
const SizedBox(height: 8),
_buildExampleCard(
'Medium (12px)',
LinearProgressBar(
maxSteps: _maxSteps,
progressType: ProgressType.linear,
currentStep: _currentStep,
progressColor: Colors.purple,
backgroundColor: Colors.grey.shade300,
minHeight: 12,
borderRadius: BorderRadius.circular(6),
),
),
const SizedBox(height: 8),
_buildExampleCard(
'Thick (24px)',
LinearProgressBar(
maxSteps: _maxSteps,
progressType: ProgressType.linear,
currentStep: _currentStep,
progressColor: Colors.purple,
backgroundColor: Colors.grey.shade300,
minHeight: 24,
borderRadius: BorderRadius.circular(12),
),
),
_buildSectionTitle('Gradient Progress'),
_buildExampleCard(
'Gradient Bar',
LinearProgressBar(
maxSteps: _maxSteps,
progressType: ProgressType.linear,
currentStep: _currentStep,
progressGradient: const LinearGradient(
colors: [Colors.blue, Colors.purple, Colors.pink],
),
backgroundColor: Colors.grey.shade300,
minHeight: 16,
borderRadius: BorderRadius.circular(8),
),
),
const SizedBox(height: 24),
_buildControlButtons(),
],
),
);
}
Widget _buildControlButtons() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton.icon(
onPressed:
_currentStep > 0 ? () => setState(() => _currentStep--) : null,
icon: const Icon(Icons.remove),
label: const Text('Decrease'),
),
const SizedBox(width: 16),
Text(
'$_currentStep / $_maxSteps',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(width: 16),
ElevatedButton.icon(
onPressed: _currentStep < _maxSteps
? () => setState(() => _currentStep++)
: null,
icon: const Icon(Icons.add),
label: const Text('Increase'),
),
],
);
}
Widget _buildSectionTitle(String title) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: Text(
title,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
),
),
);
}
Widget _buildExampleCard(String title, Widget child) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: Theme.of(context).textTheme.bodyMedium),
const SizedBox(height: 12),
child,
],
),
),
);
}
}
/// Examples of dots progress indicators
class DotsProgressExamples extends StatefulWidget {
/// Creates the dots progress examples widget.
const DotsProgressExamples({super.key});
@override
State<DotsProgressExamples> createState() => _DotsProgressExamplesState();
}
class _DotsProgressExamplesState extends State<DotsProgressExamples> {
int _currentStep = 2;
final int _maxSteps = 5;
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildSectionTitle('Basic Dots Indicator'),
_buildExampleCard(
'Horizontal Dots',
Center(
child: LinearProgressBar(
maxSteps: _maxSteps,
progressType: ProgressType.dots,
currentStep: _currentStep,
progressColor: Colors.blue,
backgroundColor: Colors.grey.shade400,
),
),
),
_buildSectionTitle('Custom Sizes'),
_buildExampleCard(
'Large Active Dot',
Center(
child: LinearProgressBar(
maxSteps: _maxSteps,
progressType: ProgressType.dots,
currentStep: _currentStep,
progressColor: Colors.orange,
backgroundColor: Colors.grey.shade400,
dotsActiveSize: 16,
dotsInactiveSize: 10,
),
),
),
_buildSectionTitle('Custom Spacing'),
_buildExampleCard(
'Wide Spacing',
Center(
child: LinearProgressBar(
maxSteps: _maxSteps,
progressType: ProgressType.dots,
currentStep: _currentStep,
progressColor: Colors.green,
backgroundColor: Colors.grey.shade400,
dotsSpacing: const EdgeInsets.symmetric(horizontal: 12),
),
),
),
_buildSectionTitle('Vertical Dots'),
_buildExampleCard(
'Vertical Layout',
Center(
child: SizedBox(
height: 150,
child: LinearProgressBar(
maxSteps: _maxSteps,
progressType: ProgressType.dots,
currentStep: _currentStep,
progressColor: Colors.purple,
backgroundColor: Colors.grey.shade400,
dotsAxis: Axis.vertical,
dotsActiveSize: 12,
dotsInactiveSize: 8,
),
),
),
),
_buildSectionTitle('Interactive Dots'),
_buildExampleCard(
'Tap to Change Step',
Center(
child: LinearProgressBar(
maxSteps: _maxSteps,
progressType: ProgressType.dots,
currentStep: _currentStep,
progressColor: Colors.teal,
backgroundColor: Colors.grey.shade400,
dotsActiveSize: 14,
dotsInactiveSize: 10,
onDotTap: (position) {
setState(() => _currentStep = position.toInt());
},
),
),
),
const SizedBox(height: 24),
_buildControlButtons(),
],
),
);
}
Widget _buildControlButtons() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton.icon(
onPressed:
_currentStep > 0 ? () => setState(() => _currentStep--) : null,
icon: const Icon(Icons.remove),
label: const Text('Previous'),
),
const SizedBox(width: 16),
Text(
'Step ${_currentStep + 1} of $_maxSteps',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(width: 16),
ElevatedButton.icon(
onPressed: _currentStep < _maxSteps - 1
? () => setState(() => _currentStep++)
: null,
icon: const Icon(Icons.add),
label: const Text('Next'),
),
],
);
}
Widget _buildSectionTitle(String title) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: Text(
title,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
),
),
);
}
Widget _buildExampleCard(String title, Widget child) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: Theme.of(context).textTheme.bodyMedium),
const SizedBox(height: 12),
child,
],
),
),
);
}
}
/// Examples of titled progress bars
class TitledProgressExamples extends StatefulWidget {
/// Creates the titled progress examples widget.
const TitledProgressExamples({super.key});
@override
State<TitledProgressExamples> createState() => _TitledProgressExamplesState();
}
class _TitledProgressExamplesState extends State<TitledProgressExamples> {
int _currentStep = 65;
final int _maxSteps = 100;
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildSectionTitle('Text Label'),
_buildExampleCard(
'Center Label',
TitledProgressBar(
maxSteps: _maxSteps,
currentStep: _currentStep,
progressColor: Colors.blue,
backgroundColor: Colors.grey.shade300,
label: 'Loading...',
labelColor: Colors.white,
minHeight: 24,
borderRadius: BorderRadius.circular(12),
),
),
_buildSectionTitle('Percentage Display'),
_buildExampleCard(
'Show Percentage',
TitledProgressBar(
maxSteps: _maxSteps,
currentStep: _currentStep,
progressColor: Colors.green,
backgroundColor: Colors.grey.shade300,
labelType: LabelType.percentage,
labelColor: Colors.white,
labelFontWeight: FontWeight.bold,
minHeight: 28,
borderRadius: BorderRadius.circular(14),
),
),
_buildSectionTitle('Step Count'),
_buildExampleCard(
'Show Step Count',
TitledProgressBar(
maxSteps: _maxSteps,
currentStep: _currentStep,
progressColor: Colors.purple,
backgroundColor: Colors.grey.shade300,
labelType: LabelType.stepCount,
labelColor: Colors.white,
minHeight: 24,
borderRadius: BorderRadius.circular(12),
),
),
_buildSectionTitle('Label Positions'),
_buildExampleCard(
'Label on Top',
TitledProgressBar(
maxSteps: _maxSteps,
currentStep: _currentStep,
progressColor: Colors.orange,
backgroundColor: Colors.grey.shade300,
labelType: LabelType.percentage,
labelPosition: LabelPosition.top,
labelColor: Colors.black87,
minHeight: 12,
borderRadius: BorderRadius.circular(6),
),
),
_buildSectionTitle('With Gradient'),
_buildExampleCard(
'Gradient + Percentage',
TitledProgressBar(
maxSteps: _maxSteps,
currentStep: _currentStep,
progressGradient: const LinearGradient(
colors: [Colors.pink, Colors.purple, Colors.blue],
),
backgroundColor: Colors.grey.shade300,
labelType: LabelType.percentage,
labelColor: Colors.white,
labelFontWeight: FontWeight.bold,
minHeight: 28,
borderRadius: BorderRadius.circular(14),
),
),
const SizedBox(height: 24),
_buildSlider(),
],
),
);
}
Widget _buildSlider() {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Text(
'Adjust Progress: $_currentStep%',
style: Theme.of(context).textTheme.titleMedium,
),
Slider(
value: _currentStep.toDouble(),
min: 0,
max: _maxSteps.toDouble(),
divisions: _maxSteps,
onChanged: (value) {
setState(() => _currentStep = value.toInt());
},
),
],
),
),
);
}
Widget _buildSectionTitle(String title) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: Text(
title,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
),
),
);
}
Widget _buildExampleCard(String title, Widget child) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: Theme.of(context).textTheme.bodyMedium),
const SizedBox(height: 12),
child,
],
),
),
);
}
}
/// Examples of circular percent indicators
class CircularPercentExamples extends StatefulWidget {
/// Creates the circular percent examples widget.
const CircularPercentExamples({super.key});
@override
State<CircularPercentExamples> createState() =>
_CircularPercentExamplesState();
}
class _CircularPercentExamplesState extends State<CircularPercentExamples> {
double _percent = 0.75;
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildSectionTitle('Basic Circular Indicator'),
_buildExampleCard(
'Simple Circle with Percentage',
Center(
child: CircularPercentIndicator(
percent: _percent,
radius: 60,
lineWidth: 10,
progressColor: Colors.blue,
backgroundColor: Colors.grey.shade300,
circularStrokeCap: CircularStrokeCap.round,
center: Text(
'${(_percent * 100).toInt()}%',
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.blue,
),
),
),
),
),
_buildSectionTitle('Gradient Circular'),
_buildExampleCard(
'With Gradient Colors',
Center(
child: CircularPercentIndicator(
percent: _percent,
radius: 70,
lineWidth: 12,
backgroundColor: Colors.grey.shade200,
linearGradient: const LinearGradient(
colors: [Colors.purple, Colors.pink, Colors.orange],
),
circularStrokeCap: CircularStrokeCap.round,
center: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'${(_percent * 100).toInt()}%',
style: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
const Text(
'Complete',
style: TextStyle(
fontSize: 12,
color: Colors.grey,
),
),
],
),
),
),
),
_buildSectionTitle('Different Sizes'),
_buildExampleCard(
'Small, Medium, Large',
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
CircularPercentIndicator(
percent: _percent,
radius: 30,
lineWidth: 6,
progressColor: Colors.teal,
backgroundColor: Colors.grey.shade300,
center: Text(
'${(_percent * 100).toInt()}%',
style: const TextStyle(
fontSize: 10, fontWeight: FontWeight.bold),
),
),
CircularPercentIndicator(
percent: _percent,
radius: 50,
lineWidth: 8,
progressColor: Colors.indigo,
backgroundColor: Colors.grey.shade300,
center: Text(
'${(_percent * 100).toInt()}%',
style: const TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
),
),
CircularPercentIndicator(
percent: _percent,
radius: 70,
lineWidth: 10,
progressColor: Colors.deepOrange,
backgroundColor: Colors.grey.shade300,
center: Text(
'${(_percent * 100).toInt()}%',
style: const TextStyle(
fontSize: 22, fontWeight: FontWeight.bold),
),
),
],
),
),
_buildSectionTitle('With Header & Footer'),
_buildExampleCard(
'Download Progress',
Center(
child: CircularPercentIndicator(
percent: _percent,
radius: 60,
lineWidth: 8,
progressColor: Colors.green,
backgroundColor: Colors.grey.shade300,
circularStrokeCap: CircularStrokeCap.round,
header: const Padding(
padding: EdgeInsets.only(bottom: 4),
child: Text(
'Downloading...',
style: TextStyle(fontWeight: FontWeight.bold),
),
),
center:
const Icon(Icons.download, size: 32, color: Colors.green),
footer: Padding(
padding: const EdgeInsets.only(top: 4),
child: Text(
'${(_percent * 100).toInt()}%',
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.green,
),
),
),
),
),
),
_buildSectionTitle('Different Start Angles'),
_buildExampleCard(
'Start from Different Positions',
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
CircularPercentIndicator(
percent: _percent,
radius: 40,
lineWidth: 8,
startAngle: CircularStartAngle.top,
progressColor: Colors.blue,
backgroundColor: Colors.grey.shade300,
),
const SizedBox(height: 4),
const Text('Top', style: TextStyle(fontSize: 12)),
],
),
Column(
children: [
CircularPercentIndicator(
percent: _percent,
radius: 40,
lineWidth: 8,
startAngle: CircularStartAngle.right,
progressColor: Colors.green,
backgroundColor: Colors.grey.shade300,
),
const SizedBox(height: 4),
const Text('Right', style: TextStyle(fontSize: 12)),
],
),
Column(
children: [
CircularPercentIndicator(
percent: _percent,
radius: 40,
lineWidth: 8,
startAngle: CircularStartAngle.bottom,
progressColor: Colors.orange,
backgroundColor: Colors.grey.shade300,
),
const SizedBox(height: 4),
const Text('Bottom', style: TextStyle(fontSize: 12)),
],
),
Column(
children: [
CircularPercentIndicator(
percent: _percent,
radius: 40,
lineWidth: 8,
startAngle: CircularStartAngle.left,
progressColor: Colors.purple,
backgroundColor: Colors.grey.shade300,
),
const SizedBox(height: 4),
const Text('Left', style: TextStyle(fontSize: 12)),
],
),
],
),
),
_buildSectionTitle('Filled Background'),
_buildExampleCard(
'With Circle Fill',
Center(
child: CircularPercentIndicator(
percent: _percent,
radius: 60,
lineWidth: 10,
progressColor: Colors.white,
backgroundColor: Colors.blue.shade100,
fillColor: true,
circleColor: Colors.blue.shade50,
circularStrokeCap: CircularStrokeCap.round,
center: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.battery_charging_full,
color: Colors.blue, size: 28),
Text(
'${(_percent * 100).toInt()}%',
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.blue,
),
),
],
),
),
),
),
_buildSectionTitle('Reversed Direction'),
_buildExampleCard(
'Counter-clockwise',
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
CircularPercentIndicator(
percent: _percent,
radius: 50,
lineWidth: 8,
progressColor: Colors.red,
backgroundColor: Colors.grey.shade300,
reverse: false,
),
const SizedBox(height: 4),
const Text('Normal', style: TextStyle(fontSize: 12)),
],
),
Column(
children: [
CircularPercentIndicator(
percent: _percent,
radius: 50,
lineWidth: 8,
progressColor: Colors.red,
backgroundColor: Colors.grey.shade300,
reverse: true,
),
const SizedBox(height: 4),
const Text('Reversed', style: TextStyle(fontSize: 12)),
],
),
],
),
),
const SizedBox(height: 24),
_buildSlider(),
],
),
);
}
Widget _buildSlider() {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Text(
'Adjust Progress: ${(_percent * 100).toInt()}%',
style: Theme.of(context).textTheme.titleMedium,
),
Slider(
value: _percent,
min: 0,
max: 1,
divisions: 100,
onChanged: (value) {
setState(() => _percent = value);
},
),
],
),
),
);
}
Widget _buildSectionTitle(String title) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: Text(
title,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
),
),
);
}
Widget _buildExampleCard(String title, Widget child) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: Theme.of(context).textTheme.bodyMedium),
const SizedBox(height: 12),
child,
],
),
),
);
}
}
/// Examples of gauge indicators
class GaugeExamples extends StatefulWidget {
/// Creates the gauge examples widget.
const GaugeExamples({super.key});
@override
State<GaugeExamples> createState() => _GaugeExamplesState();
}
class _GaugeExamplesState extends State<GaugeExamples> {
double _value = 0.65;
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildSectionTitle('Basic Gauge'),
_buildExampleCard(
'Simple Gauge Indicator',
Center(
child: GaugeIndicator(
value: _value,
size: 180,
strokeWidth: 15,
valueColor: Colors.blue,
backgroundColor: Colors.grey.shade300,
showValue: true,
),
),
),
_buildSectionTitle('Speedometer Style'),
_buildExampleCard(
'With Needle Pointer',
Center(
child: GaugeIndicator(
value: _value,
size: 200,
strokeWidth: 20,
valueColor: Colors.green,
backgroundColor: Colors.grey.shade200,
showNeedle: true,
needleColor: Colors.red,
gaugeStyle: GaugeStyle.ticked,
tickCount: 10,
showMinMax: true,
minLabel: '0',
maxLabel: '100',
valueFormatter: (v) => '${(v * 100).toInt()}',
),
),
),
_buildSectionTitle('Half Gauge'),
_buildExampleCard(
'180° Sweep Angle',
Center(
child: GaugeIndicator(
value: _value,
size: 200,
strokeWidth: 20,
valueColor: Colors.teal,
backgroundColor: Colors.grey.shade300,
startAngle: 180,
sweepAngle: 180,
showValue: true,
labelPosition: GaugeLabelPosition.center,
),
),
),
_buildSectionTitle('Gradient Gauge'),
_buildExampleCard(
'With Gradient Colors',
Center(
child: GaugeIndicator(
value: _value,
size: 200,
strokeWidth: 18,
backgroundColor: Colors.grey.shade200,
gradient: const SweepGradient(
startAngle: 2.35,
endAngle: 7.07,
colors: [
Colors.green,
Colors.yellow,
Colors.orange,
Colors.red,
],
),
gaugeStyle: GaugeStyle.modern,
tickCount: 8,
showValue: true,
),
),
),
_buildSectionTitle('Range Colors'),
_buildExampleCard(
'With Colored Ranges',
Center(
child: GaugeIndicator(
value: _value,
size: 200,
strokeWidth: 20,
backgroundColor: Colors.grey.shade200,
ranges: const [
GaugeRange(start: 0.0, end: 0.33, color: Colors.green),
GaugeRange(start: 0.33, end: 0.66, color: Colors.orange),
GaugeRange(start: 0.66, end: 1.0, color: Colors.red),
],
showNeedle: true,
needleColor: Colors.black87,
showMinMax: true,
minLabel: 'Low',
maxLabel: 'High',
showValue: true,
valueFormatter: (v) {
if (v < 0.33) return 'Good';
if (v < 0.66) return 'Normal';
return 'Alert';
},
),
),
),
_buildSectionTitle('Modern Style'),
_buildExampleCard(
'Modern Ticked Gauge',
Center(
child: GaugeIndicator(
value: _value,
size: 180,
strokeWidth: 12,
valueColor: Colors.indigo,
backgroundColor: Colors.grey.shade200,
gaugeStyle: GaugeStyle.modern,
tickCount: 12,
tickLength: 10,
tickColor: Colors.grey.shade400,
showValue: true,
valueTextStyle: const TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Colors.indigo,
),
),
),
),
_buildSectionTitle('Custom Labels'),
_buildExampleCard(
'With Title and Subtitle',
Center(
child: GaugeIndicator(
value: _value,
size: 180,
strokeWidth: 15,
valueColor: Colors.deepPurple,
backgroundColor: Colors.grey.shade300,
showValue: true,
valueFormatter: (v) => '${(v * 100).toInt()}°C',
title: const Text(
'Temperature',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
subtitle: const Text(
'Current reading',
style: TextStyle(
fontSize: 12,
color: Colors.grey,
),
),
),
),
),
_buildSectionTitle('Different Angles'),
_buildExampleCard(
'Various Sweep Angles',
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
GaugeIndicator(
value: _value,
size: 100,
strokeWidth: 10,
valueColor: Colors.blue,
backgroundColor: Colors.grey.shade300,
startAngle: 180,
sweepAngle: 180,
showValue: false,
),
const Text('180°', style: TextStyle(fontSize: 12)),
],
),
Column(
children: [
GaugeIndicator(
value: _value,
size: 100,
strokeWidth: 10,
valueColor: Colors.green,
backgroundColor: Colors.grey.shade300,
startAngle: 135,
sweepAngle: 270,
showValue: false,
),
const Text('270°', style: TextStyle(fontSize: 12)),
],
),
Column(
children: [
GaugeIndicator(
value: _value,
size: 100,
strokeWidth: 10,
valueColor: Colors.orange,
backgroundColor: Colors.grey.shade300,
startAngle: 90,
sweepAngle: 360,
showValue: false,
),
const Text('360°', style: TextStyle(fontSize: 12)),
],
),
],
),
),
const SizedBox(height: 24),
_buildSlider(),
],
),
);
}
Widget _buildSlider() {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Text(
'Adjust Value: ${(_value * 100).toInt()}%',
style: Theme.of(context).textTheme.titleMedium,
),
Slider(
value: _value,
min: 0,
max: 1,
divisions: 100,
onChanged: (value) {
setState(() => _value = value);
},
),
],
),
),
);
}
Widget _buildSectionTitle(String title) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: Text(
title,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
),
),
);
}
Widget _buildExampleCard(String title, Widget child) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: Theme.of(context).textTheme.bodyMedium),
const SizedBox(height: 12),
child,
],
),
),
);
}
}
/// Examples of animated progress bars
class AnimatedProgressExamples extends StatefulWidget {
/// Creates the animated progress examples widget.
const AnimatedProgressExamples({super.key});
@override
State<AnimatedProgressExamples> createState() =>
_AnimatedProgressExamplesState();
}
class _AnimatedProgressExamplesState extends State<AnimatedProgressExamples> {
double _value = 0.5;
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildSectionTitle('Animated Linear Progress'),
_buildExampleCard(
'Smooth Animation',
LinearProgressBar(
maxSteps: 100,
progressType: ProgressType.linear,
currentStep: (_value * 100).toInt(),
progressColor: Colors.blue,
backgroundColor: Colors.grey.shade300,
minHeight: 16,
borderRadius: BorderRadius.circular(8),
animateProgress: true,
animationDuration: const Duration(milliseconds: 500),
),
),
_buildSectionTitle('Animated Circular'),
_buildExampleCard(
'Circular Animation',
Center(
child: CircularPercentIndicator(
percent: _value,
radius: 70,
lineWidth: 12,
progressColor: Colors.purple,
backgroundColor: Colors.grey.shade300,
circularStrokeCap: CircularStrokeCap.round,
animation: true,
animationDuration: const Duration(milliseconds: 800),
animationCurve: Curves.easeInOut,
center: Text(
'${(_value * 100).toInt()}%',
style: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.purple,
),
),
),
),
),
_buildSectionTitle('Animated Gauge'),
_buildExampleCard(
'Gauge with Animation',
Center(
child: GaugeIndicator(
value: _value,
size: 200,
strokeWidth: 20,
valueColor: Colors.teal,
backgroundColor: Colors.grey.shade200,
animation: true,
animationDuration: const Duration(milliseconds: 600),
animationCurve: Curves.elasticOut,
showNeedle: true,
needleColor: Colors.red,
gaugeStyle: GaugeStyle.ticked,
showValue: true,
),
),
),
_buildSectionTitle('Different Animation Curves'),
_buildExampleCard(
'Bounce Effect',
Center(
child: CircularPercentIndicator(
percent: _value,
radius: 60,
lineWidth: 10,
progressColor: Colors.orange,
backgroundColor: Colors.grey.shade300,
animation: true,
animationDuration: const Duration(milliseconds: 1000),
animationCurve: Curves.bounceOut,
center: Text(
'${(_value * 100).toInt()}%',
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
),
_buildSectionTitle('Gradient with Animation'),
_buildExampleCard(
'Animated Gradient Progress',
Column(
children: [
LinearProgressBar(
maxSteps: 100,
progressType: ProgressType.linear,
currentStep: (_value * 100).toInt(),
progressGradient: const LinearGradient(
colors: [Colors.blue, Colors.purple, Colors.pink],
),
backgroundColor: Colors.grey.shade300,
minHeight: 20,
borderRadius: BorderRadius.circular(10),
animateProgress: true,
animationDuration: const Duration(milliseconds: 500),
),
const SizedBox(height: 20),
CircularPercentIndicator(
percent: _value,
radius: 60,
lineWidth: 12,
backgroundColor: Colors.grey.shade200,
linearGradient: const LinearGradient(
colors: [Colors.green, Colors.yellow, Colors.red],
),
animation: true,
animationDuration: const Duration(milliseconds: 800),
center: Text(
'${(_value * 100).toInt()}%',
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
const SizedBox(height: 24),
_buildAnimationControls(),
],
),
);
}
Widget _buildAnimationControls() {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Text(
'Test Animation: ${(_value * 100).toInt()}%',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () => setState(() => _value = 0),
child: const Text('0%'),
),
ElevatedButton(
onPressed: () => setState(() => _value = 0.25),
child: const Text('25%'),
),
ElevatedButton(
onPressed: () => setState(() => _value = 0.5),
child: const Text('50%'),
),
ElevatedButton(
onPressed: () => setState(() => _value = 0.75),
child: const Text('75%'),
),
ElevatedButton(
onPressed: () => setState(() => _value = 1.0),
child: const Text('100%'),
),
],
),
const SizedBox(height: 16),
Slider(
value: _value,
min: 0,
max: 1,
divisions: 100,
onChanged: (value) {
setState(() => _value = value);
},
),
],
),
),
);
}
Widget _buildSectionTitle(String title) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: Text(
title,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
),
),
);
}
Widget _buildExampleCard(String title, Widget child) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: Theme.of(context).textTheme.bodyMedium),
const SizedBox(height: 12),
child,
],
),
),
);
}
}
/// Examples of linear gauge indicators
class LinearGaugeExamples extends StatefulWidget {
/// Creates the linear gauge examples widget.
const LinearGaugeExamples({super.key});
@override
State<LinearGaugeExamples> createState() => _LinearGaugeExamplesState();
}
class _LinearGaugeExamplesState extends State<LinearGaugeExamples> {
double _value = 0.65;
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildSectionTitle('Basic Linear Gauge'),
_buildExampleCard(
'Simple Linear Gauge',
LinearGauge(
value: _value,
thickness: 20,
valueColor: Colors.blue,
backgroundColor: Colors.grey.shade300,
borderRadius: BorderRadius.circular(10),
),
),
_buildSectionTitle('With Ruler Style'),
_buildExampleCard(
'Graduated Ruler',
LinearGauge(
value: _value,
thickness: 20,
valueColor: Colors.green,
backgroundColor: Colors.grey.shade300,
rulerStyle: RulerStyle.graduated,
rulerPosition: RulerPosition.start,
majorTickCount: 11,
borderRadius: BorderRadius.circular(10),
),
),
_buildSectionTitle('With Pointer'),
_buildExampleCard(
'Triangle Pointer',
LinearGauge(
value: _value,
thickness: 20,
valueColor: Colors.purple,
backgroundColor: Colors.grey.shade300,
pointer: const PointerConfig(
style: PointerStyle.triangle,
color: Colors.red,
size: 20,
position: PointerPosition.start,
),
borderRadius: BorderRadius.circular(10),
),
),
_buildSectionTitle('With Ranges'),
_buildExampleCard(
'Color Ranges',
LinearGauge(
value: _value,
thickness: 25,
showValueBar: false,
backgroundColor: Colors.grey.shade200,
ranges: const [
LinearGaugeRange(start: 0.0, end: 0.3, color: Colors.green),
LinearGaugeRange(start: 0.3, end: 0.7, color: Colors.yellow),
LinearGaugeRange(start: 0.7, end: 1.0, color: Colors.red),
],
pointer: const PointerConfig(
style: PointerStyle.diamond,
color: Colors.black87,
size: 18,
),
rulerStyle: RulerStyle.simple,
borderRadius: BorderRadius.circular(12),
),
),
_buildSectionTitle('Interactive Gauge'),
_buildExampleCard(
'Drag to Change Value',
LinearGauge(
value: _value,
thickness: 25,
valueColor: Colors.teal,
backgroundColor: Colors.grey.shade300,
interactive: true,
animation: true,
pointer: const PointerConfig(
style: PointerStyle.arrow,
color: Colors.teal,
size: 22,
),
onValueChanged: (value) {
setState(() => _value = value);
},
borderRadius: BorderRadius.circular(12),
),
),
_buildSectionTitle('Vertical Orientation'),
_buildExampleCard(
'Vertical Linear Gauge',
Center(
child: SizedBox(
height: 200,
child: LinearGauge(
value: _value,
orientation: LinearGaugeOrientation.vertical,
thickness: 20,
valueColor: Colors.indigo,
backgroundColor: Colors.grey.shade300,
rulerStyle: RulerStyle.labeled,
pointer: const PointerConfig(
style: PointerStyle.triangle,
color: Colors.red,
size: 18,
),
borderRadius: BorderRadius.circular(10),
),
),
),
),
_buildSectionTitle('Gradient Value Bar'),
_buildExampleCard(
'With Gradient',
LinearGauge(
value: _value,
thickness: 25,
valueGradient: const LinearGradient(
colors: [Colors.blue, Colors.purple, Colors.pink],
),
backgroundColor: Colors.grey.shade200,
rulerStyle: RulerStyle.graduated,
borderRadius: BorderRadius.circular(12),
),
),
const SizedBox(height: 24),
_buildSlider(),
],
),
);
}
Widget _buildSlider() {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Text(
'Adjust Value: ${(_value * 100).toInt()}%',
style: Theme.of(context).textTheme.titleMedium,
),
Slider(
value: _value,
min: 0,
max: 1,
divisions: 100,
onChanged: (value) {
setState(() => _value = value);
},
),
],
),
),
);
}
Widget _buildSectionTitle(String title) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: Text(
title,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
),
),
);
}
Widget _buildExampleCard(String title, Widget child) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: Theme.of(context).textTheme.bodyMedium),
const SizedBox(height: 12),
child,
],
),
),
);
}
}
/// Examples of radial gauge indicators
class RadialGaugeExamples extends StatefulWidget {
/// Creates the radial gauge examples widget.
const RadialGaugeExamples({super.key});
@override
State<RadialGaugeExamples> createState() => _RadialGaugeExamplesState();
}
class _RadialGaugeExamplesState extends State<RadialGaugeExamples> {
double _value = 0.65;
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildSectionTitle('Basic Radial Gauge'),
_buildExampleCard(
'Simple Radial Gauge',
Center(
child: RadialGauge(
value: _value,
size: 200,
trackWidth: 20,
valueColor: Colors.blue,
backgroundColor: Colors.grey.shade300,
showValue: true,
),
),
),
_buildSectionTitle('With Needle Pointer'),
_buildExampleCard(
'Tapered Needle',
Center(
child: RadialGauge(
value: _value,
size: 220,
trackWidth: 15,
valueColor: Colors.green,
backgroundColor: Colors.grey.shade200,
needle: const NeedleConfig(
style: NeedleStyle.tapered,
color: Colors.red,
lengthRatio: 0.75,
showKnob: true,
knobRadius: 12,
),
showValue: true,
),
),
),
_buildSectionTitle('With Shape Pointer'),
_buildExampleCard(
'Triangle Shape Pointer',
Center(
child: RadialGauge(
value: _value,
size: 200,
trackWidth: 20,
valueColor: Colors.purple,
backgroundColor: Colors.grey.shade300,
shapePointer: const ShapePointerConfig(
style: ShapePointerStyle.triangle,
color: Colors.orange,
size: 18,
position: ShapePointerPosition.outer,
),
showValue: true,
),
),
),
_buildSectionTitle('With Ranges'),
_buildExampleCard(
'Colored Ranges',
Center(
child: RadialGauge(
value: _value,
size: 220,
trackWidth: 25,
showValueBar: false,
backgroundColor: Colors.grey.shade200,
ranges: const [
RadialGaugeRange(start: 0.0, end: 0.33, color: Colors.green),
RadialGaugeRange(
start: 0.33, end: 0.66, color: Colors.orange),
RadialGaugeRange(start: 0.66, end: 1.0, color: Colors.red),
],
needle: const NeedleConfig(
style: NeedleStyle.compass,
color: Colors.black87,
lengthRatio: 0.7,
),
showValue: true,
),
),
),
_buildSectionTitle('Interactive Gauge'),
_buildExampleCard(
'Drag to Change Value',
Center(
child: RadialGauge(
value: _value,
size: 200,
trackWidth: 20,
valueColor: Colors.teal,
backgroundColor: Colors.grey.shade300,
interactive: true,
animation: true,
needle: const NeedleConfig(
style: NeedleStyle.tapered,
color: Colors.teal,
),
onValueChanged: (value) {
setState(() => _value = value);
},
showValue: true,
),
),
),
_buildSectionTitle('Different Positions'),
_buildExampleCard(
'Start from Top/Bottom/Left/Right',
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
RadialGauge(
value: _value,
size: 80,
trackWidth: 10,
position: RadialGaugePosition.top,
valueColor: Colors.blue,
backgroundColor: Colors.grey.shade300,
),
const Text('Top', style: TextStyle(fontSize: 12)),
],
),
Column(
children: [
RadialGauge(
value: _value,
size: 80,
trackWidth: 10,
position: RadialGaugePosition.right,
valueColor: Colors.green,
backgroundColor: Colors.grey.shade300,
),
const Text('Right', style: TextStyle(fontSize: 12)),
],
),
Column(
children: [
RadialGauge(
value: _value,
size: 80,
trackWidth: 10,
position: RadialGaugePosition.bottom,
valueColor: Colors.orange,
backgroundColor: Colors.grey.shade300,
),
const Text('Bottom', style: TextStyle(fontSize: 12)),
],
),
Column(
children: [
RadialGauge(
value: _value,
size: 80,
trackWidth: 10,
position: RadialGaugePosition.left,
valueColor: Colors.purple,
backgroundColor: Colors.grey.shade300,
),
const Text('Left', style: TextStyle(fontSize: 12)),
],
),
],
),
),
_buildSectionTitle('With Ticks'),
_buildExampleCard(
'Tick Marks and Labels',
Center(
child: RadialGauge(
value: _value,
size: 220,
trackWidth: 15,
valueColor: Colors.indigo,
backgroundColor: Colors.grey.shade200,
showTicks: true,
showTickLabels: true,
majorTickCount: 11,
needle: const NeedleConfig(
style: NeedleStyle.flat,
color: Colors.indigo,
),
showValue: true,
),
),
),
const SizedBox(height: 24),
_buildSlider(),
],
),
);
}
Widget _buildSlider() {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Text(
'Adjust Value: ${(_value * 100).toInt()}%',
style: Theme.of(context).textTheme.titleMedium,
),
Slider(
value: _value,
min: 0,
max: 1,
divisions: 100,
onChanged: (value) {
setState(() => _value = value);
},
),
],
),
),
);
}
Widget _buildSectionTitle(String title) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: Text(
title,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
),
),
);
}
Widget _buildExampleCard(String title, Widget child) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: Theme.of(context).textTheme.bodyMedium),
const SizedBox(height: 12),
child,
],
),
),
);
}
}
/// Examples of linear percent indicators
class LinearPercentExamples extends StatefulWidget {
/// Creates the linear percent examples widget.
const LinearPercentExamples({super.key});
@override
State<LinearPercentExamples> createState() => _LinearPercentExamplesState();
}
class _LinearPercentExamplesState extends State<LinearPercentExamples> {
double _percent = 0.75;
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildSectionTitle('Basic Linear Percent'),
_buildExampleCard(
'Simple Percent Indicator',
LinearPercentIndicator(
percent: _percent,
lineHeight: 20,
progressColor: Colors.blue,
backgroundColor: Colors.grey.shade300,
borderRadius: BorderRadius.circular(10),
),
),
_buildSectionTitle('With Percentage Display'),
_buildExampleCard(
'Show Percentage',
LinearPercentIndicator(
percent: _percent,
lineHeight: 25,
progressColor: Colors.green,
backgroundColor: Colors.grey.shade300,
showPercentage: true,
borderRadius: BorderRadius.circular(12),
),
),
_buildSectionTitle('With Leading & Trailing'),
_buildExampleCard(
'Download Progress',
LinearPercentIndicator(
percent: _percent,
lineHeight: 20,
progressColor: Colors.purple,
backgroundColor: Colors.grey.shade300,
leading: const Icon(Icons.download, color: Colors.purple),
trailing: Text('${(_percent * 100).toInt()}%'),
borderRadius: BorderRadius.circular(10),
animation: true,
),
),
_buildSectionTitle('With Center Widget'),
_buildExampleCard(
'Center Label',
LinearPercentIndicator(
percent: _percent,
lineHeight: 30,
progressColor: Colors.teal,
backgroundColor: Colors.grey.shade300,
center: Text(
'Loading... ${(_percent * 100).toInt()}%',
style: const TextStyle(
color: Colors.white, fontWeight: FontWeight.bold),
),
borderRadius: BorderRadius.circular(15),
animation: true,
),
),
_buildSectionTitle('With Gradient'),
_buildExampleCard(
'Gradient Progress',
LinearPercentIndicator(
percent: _percent,
lineHeight: 25,
linearGradient: const LinearGradient(
colors: [Colors.pink, Colors.purple, Colors.blue],
),
backgroundColor: Colors.grey.shade200,
borderRadius: BorderRadius.circular(12),
animation: true,
),
),
_buildSectionTitle('Multi-Segment Indicator'),
_buildExampleCard(
'Multiple Segments',
MultiSegmentLinearIndicator(
segments: const [
LinearSegment(
start: 0.0, end: 0.25, color: Colors.green, label: 'Done'),
LinearSegment(
start: 0.25,
end: 0.55,
color: Colors.yellow,
label: 'Progress'),
LinearSegment(
start: 0.55,
end: 0.8,
color: Colors.orange,
label: 'Pending'),
],
lineHeight: 30,
backgroundColor: Colors.grey.shade200,
animation: true,
showLabels: true,
labelPosition: LinearChildPosition.center,
),
),
_buildSectionTitle('RTL Support'),
_buildExampleCard(
'Right to Left',
LinearPercentIndicator(
percent: _percent,
lineHeight: 20,
progressColor: Colors.indigo,
backgroundColor: Colors.grey.shade300,
isRTL: true,
showPercentage: true,
borderRadius: BorderRadius.circular(10),
),
),
_buildSectionTitle('Different Sizes'),
_buildExampleCard(
'Thin, Medium, Thick',
Column(
children: [
LinearPercentIndicator(
percent: _percent,
lineHeight: 5,
progressColor: Colors.red,
backgroundColor: Colors.grey.shade300,
borderRadius: BorderRadius.circular(2),
),
const SizedBox(height: 16),
LinearPercentIndicator(
percent: _percent,
lineHeight: 15,
progressColor: Colors.orange,
backgroundColor: Colors.grey.shade300,
borderRadius: BorderRadius.circular(7),
),
const SizedBox(height: 16),
LinearPercentIndicator(
percent: _percent,
lineHeight: 30,
progressColor: Colors.blue,
backgroundColor: Colors.grey.shade300,
showPercentage: true,
borderRadius: BorderRadius.circular(15),
),
],
),
),
_buildSectionTitle('With Animation'),
_buildExampleCard(
'Animated Progress',
LinearPercentIndicator(
percent: _percent,
lineHeight: 25,
progressColor: Colors.deepOrange,
backgroundColor: Colors.grey.shade300,
animation: true,
animationDuration: 1000,
animationCurve: Curves.easeInOut,
showPercentage: true,
borderRadius: BorderRadius.circular(12),
),
),
const SizedBox(height: 24),
_buildSlider(),
],
),
);
}
Widget _buildSlider() {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Text(
'Adjust Percent: ${(_percent * 100).toInt()}%',
style: Theme.of(context).textTheme.titleMedium,
),
Slider(
value: _percent,
min: 0,
max: 1,
divisions: 100,
onChanged: (value) {
setState(() => _percent = value);
},
),
],
),
),
);
}
Widget _buildSectionTitle(String title) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: Text(
title,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
),
),
);
}
Widget _buildExampleCard(String title, Widget child) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: Theme.of(context).textTheme.bodyMedium),
const SizedBox(height: 12),
child,
],
),
),
);
}
}