Reputation: 313
I'm trying to achieve a horizontal bar chart in flutter. I came across these packages fl_charts and charts_flutter. but I need to customise the looks to match with the following image I attached. 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.
Upvotes: 8
Views: 7089
Reputation: 37
You can use the Syncfusion's Flutter charts package, as I am using now for my application. Using Syncfusion's SfCartesianChart widget, render the bar chart along with data labels and by changing the data label's default position your output can be achieved. This widget works on Android, iOS, and web platforms.
Upvotes: 2
Reputation: 16187
Use LayoutBuilder to know the possible width, and IntrinsicWidth to calculate the place of title and numbers, but at the same time don't shrink the long title text.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: SafeArea(
child: MyHomePage(),
),
),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_title('Food Weight(grams)'),
Padding(
padding: const EdgeInsets.only(left: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ChartLine(title: 'Fat', number: 1800, rate: 1),
ChartLine(title: 'Protein', number: 600, rate: 0.4)
],
),
),
_title('Ratios'),
Padding(
padding: const EdgeInsets.only(left: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ChartLine(
title: 'Calculum/Phosporous ratio = 2:1',
rate: 0.5,
),
ChartLine(
title: 'Omega3/6 ratio = 1:4',
rate: 0.4,
),
],
),
),
],
),
);
}
Widget _title(String title) {
return Padding(
padding: const EdgeInsets.only(bottom: 8.0, top: 4),
child: Text(
title,
style: TextStyle(fontSize: 18),
),
);
}
}
class ChartLine extends StatelessWidget {
const ChartLine({
Key key,
@required this.rate,
@required this.title,
this.number,
}) : assert(title != null),
assert(rate != null),
assert(rate > 0),
assert(rate <= 1),
super(key: key);
final double rate;
final String title;
final int number;
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
final lineWidget = constraints.maxWidth * rate;
return Padding(
padding: const EdgeInsets.only(bottom: 10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
constraints: BoxConstraints(minWidth: lineWidget),
child: IntrinsicWidth(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
title,
style: TextStyle(
fontSize: 18,
),
),
if (number != null)
Text(
number.toString(),
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
],
),
),
),
Container(
color: Colors.blue,
height: 60,
width: lineWidget,
),
],
),
);
});
}
}
Upvotes: 6