'Flutter - Horizontal Bar Chart stacked in one bar chart
I'm trying to achieve this type of horizontal bar chart stacked within one Bar chart. I came across the fl_chart package, but none of it seems to have the type that I'm looking for. If any champ can support me in giving me steps to how to achieve this or an exemplary code will be so much helpful. Thank you so much in advance.
Solution 1:[1]
List<int> acc = [500, 300, 400, 900, 800];
List<Color> col = [
Colors.red,
Colors.blue,
Colors.orange,
Colors.green,
Colors.pink
];
getSum() {
return acc.reduce((a, b) => a + b);
}
getAccAver(int index) {
return (acc[index] / getSum() * 100).toInt();
}
Padding(
padding: const EdgeInsets.all(5.0),
child: SizedBox(
height: 20,
width: MediaQuery.of(context).size.width,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
for (var i = 0; i < acc.length; i++)
CardAccAve(
percentage: getAccAver(i),
leftBorder: i == 0 ? 10 : 0,
rightBorder: i == acc.length - 1 ? 10 : 0,
color: col[i],
),
],
),
),
),
class CardAccAve extends StatelessWidget {
CardAccAve({
Key? key,
required this.leftBorder,
required this.rightBorder,
required this.percentage,
required this.color,
}) : super(key: key);
double leftBorder;
double rightBorder;
final int percentage;
Color color;
@override
Widget build(BuildContext context) {
return Expanded(
flex: percentage,
child: SizedBox(
height: 20,
child: Card(
margin: const EdgeInsets.symmetric(horizontal: 1, vertical: 2),
color: color,
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(leftBorder),
topLeft: Radius.circular(leftBorder),
bottomRight: Radius.circular(rightBorder),
topRight: Radius.circular(rightBorder),
),
),
),
),
);
}
}
Result
Solution 2:[2]
You could also achieve this with a LinearGradient.
A LinearGradient takes a List<Color> colors and List<double> stops.
In order to have clear color boundaries, you duplicate the colors and stops at the boundaries.
Example:
colors: [red, red, transparent, transparent, green, green]
stops: [0.0, 0.45, 0.45, 0.55, 0.55, 1]
Full code sample
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData.light(),
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final chartData = [
Data(units: 15, color: const Color(0xFF8A5426)),
Data(units: 20, color: const Color(0xFF00BCD5)),
Data(units: 12, color: const Color(0xFF7B8700)),
Data(units: 10, color: const Color(0xFFDD8B11)),
Data(units: 50, color: const Color(0xFF673BB7)),
];
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: SizedBox(
height: 20,
child: HorizontalBarChart(
data: chartData,
),
),
),
),
);
}
}
class HorizontalBarChart extends StatelessWidget {
final List<Data> data;
final double gap;
const HorizontalBarChart({
Key? key,
required this.data,
this.gap = .02,
}) : super(key: key);
List<double> get processedStops {
double totalGapsWith = gap * (data.length - 1);
double totalData = data.fold(0, (a, b) => a + b.units);
return data.fold(<double>[0.0], (List<double> l, d) {
l.add(l.last + d.units * (1 - totalGapsWith) / totalData);
l.add(l.last);
l.add(l.last + gap);
l.add(l.last);
return l;
})
..removeLast()
..removeLast()
..removeLast();
}
List<Color> get processedColors {
return data.fold(
<Color>[],
(List<Color> l, d) => [
...l,
d.color,
d.color,
Colors.transparent,
Colors.transparent,
])
..removeLast()
..removeLast();
}
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(
Radius.circular(500),
),
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
stops: processedStops,
colors: processedColors,
),
),
);
}
}
class Data {
final double units;
final Color color;
Data({required this.units, required this.color});
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | A. Sang |
| Solution 2 | Thierry |



